1, the background

These days in WX random search keywords “front-end resume”, found a lot of personal online resume mini program, the brain suddenly also want to make a small program of their own resume. You can do it as your own personal project, and you can try it.

2. Choose frames

There are many ways to develop small programs now, which can bring us a lot of convenience, but also let the project has a certain scalability. At present, there are five popular development methods of small programs in the market: native, Tencent Wepy, Meituan MPvue, O2 Lab Taro, DCloud Company Uni-App and so on.

Below is a simple comparison of some frames:

As the main technology stack used by the company at present is React + Ts, taro is the best way to develop small programs. It is quick to use and the community is quite active. Besides, the goal of this framework is great, which is to use the React development method to write code once. Generate applications that can run in wechat applet, H5, React Native, etc., whose scalability is quite good, so selectedTaro.

3. Start building

Yarn Global add @tarojs/cli taro init My-intra-app Install plug-ins as needed: typescript\sass CD my-intra-app YARN dev: appellate

├ ─ ─ dist directory compiled results | ├ ─ ─ the config project build configuration directory | ├ ─ ─ index. The js default configuration | ├ ─ ─ dev. | js development environment configuration └ ─ ─ the prod. Js production environment configuration | ├ ─ ─ the SRC source directory | ├ ─ ─ Pages page file directory | | └ ─ ─ index index page directory | | ├ ─ ─ index. The js index page logic | | ├ ─ ─ index. The CSS style index page | | └ ─ ─ index. The config. Js Configuration index page | | | ├ ─ ─ app. Js project entry documents | ├ ─ ─ app. The CSS style of total project general | └ ─ ─ app. Config. Js project inlet configuration | ├ ─ ─ project. Config. The json WeChat applet project configuration Project.config. json ├─ project.tt.json ├─ project.config.json └ ─ project.swan.json Project. The swan. Json ├ ─ ─ project. Qq. The json qq small program project configuration project. Config. The json | ├ ─ ─ Babel. Config. Js Babel configuration ├ ─ ─ tsconfig. Json TypeScript configuration ├ ─ ─. Eslintrc ESLint configuration | └ ─ ─ package. The jsonCopy the code
SRC create several folders: API, Assets, Components, Store, and styles
  • To support modular import styles, rename the index.scss file to style.module. SCSS and set cssModules. Enable to true in the config/index.js file.
  • Rewrite the contents of index.tsx, because I’m used to functional programming, so rewrite class.
import React,{useEffect} from 'react'
import { View, Text } from '@tarojs/components'
import styles from './style.module.scss';

const Index:React.FC = props= > { 

  useEffect(() = >{})return (
      <View className={styles.index}>
        <Text>Hello world!</Text>
      </View>)}export default Index
Copy the code
  • Create several new directories under the SRC directory: API, Assets, Components, and Store
  • Open the index.js file in the config directory and set the alias path as follows:
const path = require('path') // eslint-disable-line alias Settings

const config = {
  projectName: 'my-intro-app'.date: '2021-8-26'.designWidth: 750.deviceRatio: {
    640: 2.34 / 2.750: 1.828: 1.81 / 2
  },
  sourceRoot: 'src'.outputRoot: 'dist'.plugins: [].defineConstants: {},copy: {
    patterns: [].options: {}},framework: 'react'.mini: {
    postcss: {
      pxtransform: {
        enable: true.config: {}},url: {
        enable: true.config: {
          limit: 1024 // Set the maximum conversion size}},cssModules: {
        enable: true.// The default is false, or true if you want to use CSS modules
        config: {
          namingPattern: 'module'.// Switch mode. The value can be global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]'}}}},h5: {
    publicPath: '/'.staticDirectory: 'static'.postcss: {
      autoprefixer: {
        enable: true.config: {}},cssModules: {
        enable: true.// The default is false, or true if you want to use CSS modules
        config: {
          namingPattern: 'module'.// Switch mode. The value can be global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]'}}}},alias: {
    '@api': path.resolve(__dirname, '.. '.'src/api'),
    '@components': path.resolve(__dirname, '.. '.'src/components'),
    '@assets': path.resolve(__dirname, '.. '.'src/assets'),
    '@store': path.resolve(__dirname, '.. '.'src/store')}}module.exports = function (merge) {
  if (process.env.NODE_ENV === 'development') {
    return merge({}, config, require('./dev'))}return merge({}, config, require('./prod'))}Copy the code

To avoid alias import errors, locate the tsconfig.json file and add the following code:

    "paths": {
            "@src/*": ["src/*"]."@config/*": ["src/config/*"]."@store/*": ["src/store/*"]."@views/*": ["src/views/*"]."@components/*": ["src/components/*"]."@services/*": ["src/services/*"]."@styles/*": ["src/styles/*"]},Copy the code

• Create a store/index.js file in the SRC directory using redux status management and write the following:

import { createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from '@redux/reducers'

const composeEnhancers =
  typeof window= = ='object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
    }) : compose

const middlewares = [
  thunkMiddleware
]

/** * redux- Logger middleware that prints the status of the Action and its Store in the console when it is initiated */
if (process.env.NODE_ENV === 'development'&& process.env.TARO_ENV ! = ='quickapp') {
  
  middlewares.push(require('redux-logger').createLogger())
}

constenhancer = composeEnhancers( applyMiddleware(... middlewares), )export default function configStore () {
  const store = createStore(rootReducer, enhancer)
  return store
}
Copy the code

SRC directory to create redux directory, and create respectively: Action directory /login.ts, reducers directory /user.ts, constants/index.ts. • Reducers /user.ts

import { SET_IS_LOGIN,SET_LOGIN_INFO } from '.. /constants'

// Initial state
const INITIAL_STATE = {
    avatar: ' './ / avatar
    nickName: ' '.// wechat nickname
    isLogin: false.// Initial login status
}

export default function user (state = INITIAL_STATE, action) {
  switch (action.type) {
    case SET_IS_LOGIN:
      // Login status
      const isLogin = action.payload
      return {
        ...state,
        isLogin
      };
    case SET_LOGIN_INFO: 
      // Avatar and nickname
      const { avatar, nickName } = action.payload
      return {
        ...state,
        avatar,
        nickName
      }
    default:
      return state
  }
}
Copy the code

• The action/login.ts code is as follows:

import { SET_IS_LOGIN,SET_LOGIN_INFO } from '.. /constants'

// Set the login status
export const setLogin = () = > {
  return {
    type: SET_IS_LOGIN
  }
} 

// Set the login information
export const setUserInfo = () = >{
  return {
    type: SET_LOGIN_INFO
  }
}
Copy the code

How to use it? Login popup to use:

/** * Global login popup */
import React, { useEffect } from 'react';
import { Button, View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import styles from './style.module.scss';
import { useSelector,useDispatch } from 'react-redux' 
import { SET_IS_LOGIN,SET_LOGIN_INFO } from '@redux/constants'
import {setStorageSync} from '@utils/storage'  

interface Iprops {
    setLoginHide:() = >void  // Close the popover
}

const LoginModal: React.FC<Iprops> = props= > {  
    const {setLoginHide} = props
    
    / / use useDispatch
    const dispatch = useDispatch()

    // Check whether the user is authorized to log in via wechat
    const getUserfile = () = > {
        Taro.getUserProfile({
            // Specify the purpose of obtaining the user's personal information, which will be displayed in the subsequent pop-up window
            desc: 'For personal Data'.success: (res) = > {
                const {avatarUrl,nickName} = res.userInfo
                
                // Store user information in the cache
                setStorageSync('userInfo', {avatar: avatarUrl, nickName:nickName })
                setStorageSync('isLogin'.true)

                // Call action to set the login status
                dispatch({ type: SET_IS_LOGIN,payload: {isLogin:true}})// Set redux to store avatar and nickname
                dispatch({ type: SET_LOGIN_INFO,payload: {avatar: avatarUrl,
                    nickName: nickName
                } }) 

                // Hide the login popover
                setLoginHide()
                console.log('Get user information',res.userInfo);
            },
            fail: (res) = > {
                setStorageSync('isLogin'.false)
                Taro.showToast({title:'Fetch failed'.icon:'none'})
                console.log(res);
            },
            complete: (res) = > {
                console.log(res); }})}return (
        <View className={styles.lgmodalbox}>
            <View className={styles.box}>
                <View className={styles.txt}>Please click login</View>
                <Button type="primary" onClick={getUserfile} className={styles.btn}>The login</Button>
            </View>
        </View>)}export default LoginModal
Copy the code

scan