preface

It has been almost a year since Vue3.0 was officially released, and Vite, a faster packaging tool, has been updated to version 2. X. I believe that many friends have already used it in the company’s new projects and experienced this pleasure. The following article summarizes the project based on vite2.x + Vue3.0 commonly used small base operations.

Certified components

Most of the time in a development project it is necessary to use UI framework components to quickly develop and build our pages. When we use component libraries, we load on demand in order to reduce the package size (Tree-Shshaking technology).

Using the Vant component as an example, we would normally:

import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);

// Import components
import {
  Progress,
  Picker,
  Popup,
  ....
} from "vant";

/ / app. Use () to register
app.use(Progress)
   .use(Picker)
   .use(Popup)
   ...
   .mount("#app");

Copy the code

A simple reference to a few components is fine, it doesn’t look like it’s going to pull a thread, but let’s just introduce them. Twenty or thirty components is too long and will make main.ts bigger and bigger.

Create a config folder in the vant. Config. ts file name

import {
  Progress,
  Picker,
  Popup,
  ....
} from "vant";

const components = {
  Progress,
  Picker,
  Popup,
  ....
}

//.use will automatically find the install method internally to call the registered mount
const componentsInstallHandler = {
    install(app) {
        Object.keys(components).forEach(key= > app.use(components[key]))
    }
}

export default componentsInstallHandler
Copy the code

In the main. Ts

/ /... Omit the createApp introduction

/ / import
import vantComponentsInstall from "./config/vant.config";

app
  .use(vantComponentsInstall)
  .mount("#app");
Copy the code

Is it more comfortable after the operation

Component Global Registration

If you write a component such as

and want to use it globally, you can register it globally by calling the Component function returned by createApp()

/ /... Omit the createApp introduction

import Header from '@/components/Header/Index.vue'

app.component('Header', Header)
Copy the code

The filter

In 3.x, the filter has been removed and is no longer supported. Instead, you can replace it with method calls or computed properties.

<template> <div> {{computedFunc('computed')}} </div> </template> <script lang="ts"> import { computed, defineComponent} from "vue"; Export default defineComponent({setup() {// use closure to accept const computedFunc = () => {return val => val} return { computedFunc } } }) </script>Copy the code

Global filter

For example, data rendered on multiple components needs to be decrypted before being displayed correctly, and it is not possible for each component to have computed. In this case, use the global attribute to use the rendered data on all components:

// main.ts
const app = createApp(App)

app.config.globalProperties.$filters = {
  decrypt(value) {
    return mdDecrypt(value)
},
Copy the code

Then, you can modify all the templates using the $filters object:

<template>
  <p>{{ $filters.decrypt(encryptVal) }}</p>
</template>
Copy the code

Custom UI frame theme colors

Each designer uses a different theme color, the UI framework default theme color is not what we want, presumably we need to customize it. Take Vant as an example:

import { defineConfig } from 'vite'

export default defineConfig({
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true.// Custom style variable names are required
        modifyVars: {           
          'blue': '#00C6B8'.'gray-7': '# 333333'.'gray-4': '#00C6B8'. },},},},},})Copy the code

Service Agent Server

Vite can add proxyTable in config/index.js, Vite can also add proxyTable in Vite website. Here’s how to configure it:

import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    port: 3006.// Set the port to 3000 by default
    open: true.// Set the browser to automatically open on startup
    cors: true.// Allow cross-domain
    host:'10.x.x.x'.// Local IP access, how to mobile terminal mobile phone debugging need to fill in the local IP
    proxy: {
      '/api': {
        target: 'http://10.x.x.x.x'.changeOrigin: true.secure: false.rewrite: path= > path.replace('/api/'.'/')}// Configure multiple continuations
      '/api2': {... }}},})Copy the code

Configure an alias

There are many ways to write this, either as an object, or as a {find, replacement}

import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'

export default defineConfig({  
  resolve: {      
    alias: [{find: "@".replacement: resolve(__dirname, "src"),}, {find: "@ASS".replacement: resolve(__dirname, "src/assets"),},]},server: {... }})Copy the code

Mobile REM adaptive

Amfe-flexible and PostCSS-PxToREM are used in combination for mobile terminal adaptation.

amfe-flexible

Amfe-flexible is a scalable layout scheme with 1REM set to viewWidth/10.

postcss-pxtorem

Postcss-pxtorem is a postCSS plug-in that generates REM units from pixel units.

NPM install

npm i amfe-flexible -D
npm i postcss-pxtorem -D
Copy the code

After the installation, import the AMFE-Flexible plug-in into main.ts

// ...
import 'amfe-flexible/index.js'
Copy the code

Postcss – pxtorem configuration

You can configure postcss-pxtorem in one of the following modes: vtE.config. ts,.postcss.rc. ts, and postcss.copnfig. Ts.

The configuration in vite.config.ts is as follows:

import { defineConfig } from 'vite'

export default defineConfig({
  css: {... .loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-pxtorem') ({rootValue: 37.5.// Divide the width of the design by 10. Assume that the design is 375, that is, set the rootValue to 37.5
            propList: [The '*'] // // propList is to set the properties that need to be transformed, here * is to transform everything.})]}}},})Copy the code

For the root directory, create.postcssr. ts or postcss.copnfig. Ts as follows:

module.exports = {
  plugins: {
    autoprefixer: {
      overrideBrowserslist: [
        'the Android 4.1'.'iOS 7.1'.'Chrome > 31'.'ff > 31'.'ie >= 8'.'last 10 versions'.// Use the last 10 versions of all major browsers
      ],
    },
    postcss-pxtorem: {
      rootValue: 37.5.propList: [The '*'],}}},Copy the code

After the configuration, restart to see the effect:

You can also introduce rem.js, but when you need to write your own px to REM, the good news is that there is a px to REM plug-in in the VSCode extension store, which can be expanded here, you can Google it.

The environment variable

Sometimes the project development needs to be deployed in three running environments, such as test environment (Test), development environment (Dev), and generation environment (PROD). The requested interface address also needs to be changed. How to change dynamically? Vite exposes environment variables on a special import.meta. Env object, which can be used to determine which environment it is running in.

NPM run dev Run import.meta. Env to expose variable value development

NPM run build import.meta. Env exposes the value of the variable production

There is also a test environment (test) how to get?

You can configure the scripts run command using package.json

  "scripts": {
    "dev": "vite"."build": "vite build"."test:build": "vite build --mode test",},Copy the code

Run NPM run test:build import.meta. Env to expose the value of the variable as test –mode XXX name can be customized

Request URL unified management config.ts:

export const DEV_BASE_URL = "https://xxx"
export const TEST_BASE_URL = "https://xxx"
export const PRO_BASE_URL = "https://xxx"
Copy the code

Take encapsulating axiOS to set baseURL as an example:

import { DEV_BASE_URL, PRO_BASE_URL, TEST_BASE_URL, TIMEOUT } from "./config";

const envMap = {
  development: DEV_BASE_URL,
  production: PRO_BASE_URL,
  test: TEST_BASE_URL,
};

const base_URL = envMap[import.meta.env.MODE];

// axios
const instance = axios.create({
  baseURL: base_URL,
  timeout: 30000});Copy the code

Remove console.log and vconsole debugging

In vue-CLI we can configure the configureWebpack removal to see how vite is removed based on the build environment:

/ /... import
import { defineConfig, loadEnv, ConfigEnv, UserConfigExport } from "vite";

export default ({ command, mode }): UserConfigExport= > {
  const isEnvProduction = mode === "production"
  return defineConfig({
    / /... Other configuration
    build: {
      terserOptions: {
        compress: {
          drop_console: isEnvProduction, // True is closed
          drop_debugger: isEnvProduction,
        },
      },
    },
  });
};
Copy the code

Env cannot be retrieved from the configuration file by import.meta. Env, because it is exposed in the client source code, so we can retrieve the environment variable by returning a function in the mode parameter that the function receives.

Hooks used

The most annoying aspect of upgrading Vue3 is not the Compostion API syntax, but the way it gives us a new way of thinking about organizing code.

After learning the Compostion API at the beginning of the release of Vue3.0, the code also follows the correct usage of the Compostion API. However, when the components are large, the logic is complex, and the amount of code is also a lot, it is found that the maintainability is worse than the Options API.

The following explanations are combined with real business requirements

For example, there is a method to obtain verification code, click to obtain the end of the 60s after the countdown to obtain again, normal pilak balla we will write like this:

example.vue

<template> <button @click="onGetCode">{{ codeText }}</button> </template> <script lang="ts"> import { defineComponent, reactive, toRefs } from "vue"; export default defineComponent({ setup(props, ctx) { const state = reactive({ isGetCode: false, codeText: CountDown: 60, phone: Const countTime = () => {state.isgetCode = true let timer timer = setInterval((function setIntervalFunc() { if (countDown ! == 0) {state.codetext = 'Resend ${countdown. value--}'} else {state.isgetCode = false state.codetext = 'Get verification code' state.countDown = 60 clearInterval(timer) } return setIntervalFunc })(), Const onGetCode = async () => {const {success, message } = await getPhoneCode(encrypt(state.phone)) if (success) { countTime() Toast.success(message) } } return { ... toRefs(state), onGetCode } } }) </script>Copy the code

The Compostion API is used in the Compostion API. The Compostion API is used in the Compostion API. The Compostion API is used in the Compostion API, and the Compostion API is used in the Compostion API.

So you can split the logic into a separate file

// useVerificationCode.js
import { reactive, toRefs } from "vue";

export default const useVerificationCode = () = > {
    const state = reactive({
        isGetCode: false.codeText: 'Get verification code'.countDown: 60.phone: ' '
    })
    // Click after the countdown
    const countTime = () = > {
        state.isGetCode = true
        let timer
        timer = setInterval((function setIntervalFunc() {
                if(countDown ! = =0) {
                    state.codeText = 'Resend${countDown.value--}`
                } else {
                    state.isGetCode = false
                    state.codeText = 'Get verification code'
                    state.countDown = 60
                    clearInterval(timer)
                }
                return setIntervalFunc
            })(),
            1000)}// Get the verification code request
    const onGetCode = async() = > {const { success, message } = await getPhoneCode(encrypt(state.phone))
        if (success) {
            countTime()
            Toast.success(message)
        }
    }
    return {
        ...toRefs(state)
        onGetCode,
    }
}
Copy the code

And look at the retrofit:

// example.vue <template> <button @click="onGetCode">{{ codeText }}</button> </template> <script lang="ts"> import { defineComponent } from "vue"; // Import useverificationcode. js import useVerificationCode from "./ useverificationCode.js "; Export default defineComponent({setup(props, CTX) {const {onGetCode, isGetCode, codeText, countDown, phone } = useVerificationCode() // ... / /... return { onGetCode, isGetCode, codeText, countDown, phone } } }) </script>Copy the code

In the example given by the government, it does not emphasize the logic reuse, but the logical separation of concerns. I believe that everyone can understand how to write this. But in components of simple logic, there is no need to pull too much away.

conclusion

At present, my own application of Vue3.0 in the development of small projects have not encountered a big pit, facing Baidu, documents can be easily solved, quickly use it, two words good, Vite compilation is really fast ~, especially big geili ( ̄▽ ̄).