Technical Framework: Next-js (PC)

When considering the implementation of PC pages, this type of website will consider SEO optimization retrieval problems, so Next. Js is used as a backup, the page content is pre-rendered, and relevant high-frequency retrieval words can be inserted with Meta tags. You can also use the getServerSideProps() and getStaticProps() methods provided by next.js to inject Props and bind the template engine to the browser for rendering. Next, js presets

export async function getServerSideProps() {
  const res = await fetch(`https://api.apiopen.top/getSingleJoke? sid=28654780`)
  const data = await res.json()
  return { props: { data } }
}
 export async function getStaticProps() {
  const res = await fetch('... ')
  const posts = await res.json()
  return {
    props: {
     return { props: { data } }
    },
  }
}
Copy the code

componentization

Simple talk about modular, we need packaging in judging whether a reusable component, is to look at the occurrences of the component, or the amount of code component is different from person to person, but I for the sake of unity, strict code will be the most functional modules are modular components out of (if not considering itself will be reuse); As componentization pull away, we will face component state management problem, this time in the React in fact there are many ways to control, such as useContext useRef – useImperativeHandle, redux, custom event functions, then the use which actually need to root It is determined by the nesting depth of the current component. For example, if there is a subcomponent in a Nav component, we can control the state of the subcomponent by clicking the Nav component. In this case, we can simply use the custom event function to transfer the state value, or use useref-useImperativeHandle to reference the subcomponent Part of the method control state; However, if the hierarchy becomes three levels, things will become complicated if we use the above two methods. In this case, the advantages of useContext can be naturally shown. However, if there are more and more states,useContext will become jumbled. This is where Redux’s strengths come into play; I tried several approaches on the project, but in the end I cut them out and used Redux for centralized management, because Redux brings a unified development paradigm that doesn’t care about the nesting hierarchy between components; Redux configuration; In addition, rewriting Redux will have some impact on the packaging of components, as detailed in the warehouse code;

Component packaging

Here are some examples of component encapsulation (without Redux control state):

dialog

Scroll lock

  useEffect(() = >{
    if(DefaultLoginModeltatus==true||AnotherLoginWaysModelStatus==true) {window.onscroll = function() {
        let duration = document.documentElement.scrollTop || document.body.scrollTop;
        console.log("Monitoring distance from top",duration);
        if(duration>0) {const Tags:any=document.getElementById("body")
          Tags.scrollIntoView({ block: 'start'})
          // Jump to anchor point;}}}else{
      window.onscroll=null;
      // False state release;
    }
  },[DefaultLoginModeltatus,AnotherLoginWaysModelStatus])
Copy the code

Select select

Right click on the menu

.

The notes page enters here

I adopted the edit areaGithub.com/imzbf/md-ed…This markDown editor;If it wraps itself it takes a long time to process, so it’s a great library; The rich text principle is implemented through the contentEditable property and document.execcommand ()API; Interested diggers can delve into it;

< div id = "textArea" className = {styles. The text} suppressContentEditableWarning contentEditable = "true" > text < / div > document.execCommand("bold")Copy the code

Inside the markDown editor is essentially a string stream, which can be downloaded through the following code;

  const saveTopdf=() = >{
        const textArea=document.getElementById("textArea")
        const a =document.createElement('a')
        const blob=new Blob([localStorage.getItem("data")])
        const dataUrl=URL.createObjectURL(blob)
        a.href=dataUrl
        a.download="document.md"
        a.click()
    }
Copy the code

layout

Let’s talk a little bit about style layout. Style layout is something that we often neglect. We have to evaluate the complexity of a PC page before we develop it. Here I scale the PC page directly (no responsive layout, mobile web will be developed separately); The tradeoff here should be whether the complexity and features of the components are appropriate for mobile web pages; Another detail is that you need to pay attention to the drag and drop of the web window, which must be used in styleoverflowTo process; For example, the following page layout is drag-and-drop;

Run the project

Code warehouse

 npm install 
 node server.js
Copy the code

All dependent (PC) : "dependencies" : {" antd ":" ^ 4.17.3 ", "axios" : "^ 0.24.0", "Babel - plugin - import" : "^ 1.13.3", "express" : "^ 4.17.1 logger", ""," ^ 0.0.1 ", "md - editor - rt" : "^ 1.4.2", "next" : "12.0.7", "the next - the plugin - antd - less" : "^ 1.6.0 next - remove -", "imports" : "^ 1.0.6", "node - fetch" : "^ 3.1.0", "node - sass" : "^ 7.0.0", "peer" : "^ 0.6.1", "react" : "17.0.2", "the react - dom" : "17.0.2", "the react - redux" : "^ 7.2.6", "story" : "^ 4.1.2", "story - devtools - the extension" : "^ 2.13.9 redux", "- the logger" : "^ 3.0.6", "the story - the saga" : "^ 1.1.3", "the story - thunk" : "^" against 2.4.1, "sass" : "^ 1.45.0", "socket. IO" : "^ 4.4.0 socket. IO -", "client" : "^ 4.4.0",, "devDependencies" : {} "@ types/node" : "16.11.12", "@ types/react" : "" eslint 17.0.37", ", "^ 8.5.0", "eslint - config - the next" : "12.0.7", "the react - socket - IO" : "^ 0.2.5", "typescript" : "4.5.3}"Copy the code

Technical Framework :Expo(Mobile)

The react-native development program is cumbersome, often causing errors in configuring cache, packaging environment, variables, and permissions. It requires repeated debugging and tedious startup. Therefore, I adopted Expo as the default workflow for adaptive development on the mobile terminal. The API and packaging tool environment provided by Expo are well compatible with packaging, so it is recommended to use.

Mobile layout

The layout of mobile terminal is different from that of PC web page, and it mainly relies on navigation library for adaptation, but we should pay attention to the version problems. Of course,Expo has dealt with them for us, and generally no errors will be reported. Since I migrated them in the native development way, I used the 5.x version, while Expo provides the latest version. Notice that when we click on a button to go to the Stack page, we need to hide the Tab page, so we need to make the first page the Stack page, and fill the Tab page inside the Stack page; A code example is as follows:

function HomeTabs() {
  return (
    <Tab.Navigator
      tabBarOptions={{ activeTintColor: "#972F97", inactiveTintColor: "gray"}}screenOptions={({ route}) = >({ activeTintColor: "#972F97", inactiveTintColor: "gray", headerShown: false, tabBarIcon: ({ focused, size, color }) => { let icon; If (route. Name === "home ") {icon = 'focused'?<Image
                source={require("./assets/images/key1.png")}
                style={{ width: 29.height: 25}} / >
            ) : (
              <Image
                source={require("./assets/images/key0.png")}
                style={{ width: 27.5.height: 25}} / >); } else if (route. Name === "my ") {icon = 'focused'?<Image
                source={require("./assets/images/my1.png")}
                style={{ width: 31.height: 25}} / >
            ) : (
              <Image
                source={require("./assets/images/my0.png")}
                style={{ width: 29.height: 25}} / >
            );
          } else if (route.name == " ") {
            icon = focused ? (
              <Image
                source={require("./assets/images/addfill2.png")}
                style={styles.add}
              />
            ) : (
              <Image
                source={require("./assets/images/addfill2.png")}
                style={styles.add}
              />); } return icon; }})} ><Tab.Screen name="Home page" component={TabScreenA} />
      <Tab.Screen name="" component={TabScreenC} />
      <Tab.Screen name="I" component={TabScreenB} />
    </Tab.Navigator>
  );
}

export default function App() {
  const isLoadingComplete = useCachedResources();
  const colorScheme = useColorScheme();
  if(! isLoadingComplete) {return null;
  } else {
    return (
      <SafeAreaProvider style={styles.container}>
        <Provider store={Store}>
          <NavigationContainer>
            <Stack.Navigator>
              <Stack.Screen
                name="Home"
                component={HomeTabs}
                options={{ header:() = > null }}
              />
              <Stack.Screen name="Screen_G" component={ScreenG} />
              <Stack.Screen name="Screen_E" component={ScreenE} />
              <Stack.Screen
                name="TheoryDescScreen"
                component={TheoryDescScreen}
                options={{
                  title:'details',headerTitleStyle:{fontSize:15}
                }}
              />
              <Stack.Screen
                name="ErrorDescScreen"
                component={ErrorDescScreen}
                options={{
                  title:'details',headerTitleStyle:{fontSize:15}
                }}
              />
              <Stack.Screen
                name="ExampleDescScreen"
                component={ExampleDescScreen}
                options={{
                  title:'details',headerTitleStyle:{fontSize:15}
                }}
              />
              <Stack.Screen
                name="QuestionDescScreen"
                component={QuestionDescScreen}
                options={{
                  title:'details',headerTitleStyle:{fontSize:15}
                }}
              />
            </Stack.Navigator>
          </NavigationContainer>
        </Provider>
      </SafeAreaProvider>); }}Copy the code

React-native is a class of CSS styles (as follows):

let MainHeight = Dimensions.get("window").height;
let MainWidth = Dimensions.get("window").width;
const styles = StyleSheet.create({
  container: {
    flex: 1.backgroundColor: "#efefef",},nav: {
    flexDirection: "row".justifyContent: "space-between".marginHorizontal: 5,},input: {
    flex: 1,},input: {
    height: 60.width: MainWidth * 0.8.borderBottomColor: "black",},subBtn: {
    width: MainWidth * 0.2.backgroundColor: "Rgba (151,47,151, 0.7)".color: "white".alignItems: "center".justifyContent: "center",},textDefault: {
    color: "white".fontSize: 13,}});<Text style={styles.textDefault}>Submit questions</Text>
Copy the code

Comment tree data structures

const [comment, setCommentData] = useState([
    {
      id: 0.publisher: "Li Fei".content:
        "This article is really good, I follow this process in the development of execution, perfect solution to my problem;".childrenComment: [{id: 0.publisher: "Yang".content: I don't think so..parentId: 0.anwser: "Li Fei"}, {id: 1.publisher: "Yellow sea".content: "I agree with you.".parentId: 0.anwser: "Yang",},],}, {id: 1.publisher: "Li Haixin".content: "Why don't I get this data stream?".parentId: null}, {id: 2.publisher: "Chen Xinyi".content: "I thought it was good, too!".parentId: 0}, {id: 3.publisher: "胡斌".content: "How does React work?".parentId: null.childrenComment: [{id: 0.publisher: "Yang".content: I don't think so..parentId: 0.anwser: "Li Fei"}, {id: 1.publisher: "Yellow sea".content: "This article is of very high quality.".parentId: 0.anwser: "Yang",},],},]);Copy the code

Comment Tree component

    <View
        style={{
              width: MainWidth * 0.95.flex: 1.backgroundColor: "white".justifyContent: "center".marginBottom: 60,
            }}
          >
            {comment.map((item) = > {
              if(item.childrenComment ! =null) {
                return (
                  <>
                    <View
                      style={{
                        borderBottomWidth: 1.borderBottomColor: "rgb(180.180.180) ",padding: 3,}} >
                      <View
                        style={{
                          width: "100% ",height: 50.backgroundColor: "white",
                          flexDirection: "row,}} ">
                        <Image
                          source={require("././assets/images/solve.jpg")}
                          resizeMode="cover"
                          style={{ width: 50.height: 50 }}
                        ></Image>
                        <View
                          style={{
                            width: 100.height: 50, / /backgroundColor: "orange",
                            flexDirection: "column",
                            justifyContent: "center",
                            marginTop: - 8 -.marginLeft: 5,}} >
                          <Text>{item.publisher}</Text>
                          <Text
                            style={{ fontSize: 10.color: "rgb(100.100.100}}) ">Three days ago</Text>
                        </View>
                      </View>
                      <Text style={{ marginTop: 5.marginBottom: 5}} >
                        {item.content}
                      </Text>
                      <Comment childrenComment={item.childrenComment} toggleModal={toggleModal} />
                    </View>
Copy the code

Comment subcomponent

const Comment = (props) = > {
  return (
    <View
      style={{
        marginLeft: 10.backgroundColor: "rgb(230.230.230) ",padding: 5,}} >
      {props.childrenComment.map((item) => {
        return (
          <View
            style={{
              flexDirection: "row",
              justifyContent: "space-between",
              marginTop: 3,}}key={props.childrenComment.id}
          >
            <Text>Reply {item. Publisher} {item. The anwser}, {item. The content}</Text>
            <TouchableOpacity onPress={()= > props.toggleModal()}>
              <FontAwesome name="commenting-o" size={18} color="gray" />
            </TouchableOpacity>
          </View>
        );
      })}
    </View>
  );
};
Copy the code
End result:

Run the project

Need to install AndroidStudio, configure SDK, JDK; Code warehouse

npm install 
yarn start
Copy the code

{"@expo/vector-icons": "^12.0.0", "@lucarestagno/use-deep effect": "^ 1.0.7", "@ the react - navigation/bottom - tabs" : "^ 6.0.5/6.5.4", "@ the react - navigation/native" : "^ 6.0.2," "@ the react - navigation/native - stack" : "^ 6.1.0", "@ the react - navigation/stack" : "^ 5. X", "@ wxik/core" : "^ 0.5.3", "expo" : "~ 44.0.0", "expo - asset" : "~ 8.4.4", "expo - constants" : "~ 13.0.0", "expo - the font" : "~ 10.0.4 expo", "- the image - picker" : "~ 12.0.1", "expo - linking" : "~ 3.0.0", "expo - splash screen -" : "~ 0.14.0 expo", "- the status bar" : "^ 1.2.0", "expo - a web browser -" : "~ 10.1.0" and "react" : "17.0.1", "the react - dom" : "17.0.1", "the react - native" : "0.64.3", "the react - native - elements" : "^ 3.4.2", "the react - native - gesture - handler" : "^2.2.0", "react-native markdown-display": "^6.1.6", "react-native markdown-renderer": "^3.2.8", "react-native modal": "^ 13.0.0 react - native -", "pell - rich - editor" : "^ 1.8.8", "the react - native - safe - area - the context" : "3.3.2", "react-native screens": "~3.10.1", "react-native syntax-highlighter": "^2.1.0", "react-native vector-icons": "^ 9.0.0 react - native -", "web" : "0.17.1", "the react - native - webview" : "^ 11.17.0", "the react - redux" : "^ 7.2.6", "story" : "^ 4.1.2 redux -", "thunk" : "^ against 2.4.1"}, "devDependencies" : {" @ Babel/core ":" ^ 7.12.9 ", "@ types/react" : "~ 17.0.21", "@ types/react - native" : "~ 0.64.12", "jest" : "^ 26.6.3", "jest - expo" : "~ 44.0.1", "the react - test - the renderer" : "17.0.1", "typescript" : "~ 4.3.5"},Copy the code

The above is a brief copy of the front end of the record, of course, there are many details are not explained, the code can be compared; At present, it has realized its core business functions. Interested in digging friends can communicate and continue to develop.