▌ This series of articles is too long to be digested separately:

  • Front end framework: Vite2 + VUe3 +typescript+ AXIos + Vant
  • [Front end framework: Vite2 +vue3+typescript+ AXIos + Vant mobile framework combat project details (ii)](juejin.cn/post/705857…)
  • Front end framework: Vite2 + VUe3 +typescript+ AXIos + Vant mobile terminal framework)
  • Front end framework: Vite2 + VUe3 +typescript+ AXIos + Vant

☞ Point: vue3

V3.cn.vuejs.org/guide/intro…

Vite was originally created as the future foundation for vue.js development tools. Although Vite 2.0 doesn’t rely on any framework at all, the official Vue plug-in still provides first-priority support for Vue’s single-file component format, covering all advanced features such as template resource reference resolution, < Script Setup >,

Vue3 Setup syntax sugar and dodging matters

V3.vuejs.org/api/sfc-scr…

What is ❓script Setup?

Script Setup, a new syntax sugar introduced in VUE3, is a compile-time syntax sugar for using composite apis in single-file components (SFC) to simplify lengthy template code using the Composition API. Better run-time performance (its templates are programmed to render functions in the same scope, without any intermediate proxies)

For example, we wrote before when we didn’t use grammar sugar:

​
<script lang="ts">
import { defineComponent, ref } from 'vue'
import { HelloWord } from '@/components'
export default defineComponent({
​
  setup() {
    const count = ref(0)
    const inc = () => count.value++
 
    return {
      count,
      inc,
    }
  },
})
​
</script>
Copy the code

After refactoring using the Script Setup syntax sugar, will become

​
<script setup lang="ts">
import { defineComponent, ref } from 'vue'
import { HelloWord } from '@/components'
 
defineProps<{
    name:string
}>()
​
const count = ref(0)
const inc = () => count.value++
 
</script>
​
Copy the code

Script Setup syntax sugar refactored code becomes more readable and elegant 🤭🤭🤭

Basic usage

To use the Script Setup syntax, simply add the setup attribute to the script tag in the original vue file.

<script setup lang="ts">
​
</script>
Copy the code

The timing of setup execution

  • Execute (once) before the beforeCreate, before the component object is created
  • This is undefined. This cannot be used to access data/computed/methods/props. It can be imported in the VUE module
  • This is not true of any composition API callbacks

Use the parameters in Setup

<script setup="props, context" lang="ts">
 
</script>
Copy the code

Destruct syntax is also supported

​
<script setup="props, { emit }" lang="ts">
 
</script>
Copy the code

Expose variables to templates

If you want to use the setup variable in template

Return is required if syntactic sugar is not applicable, as in the above example

 return {
      count,
      inc,
    }
Copy the code

You don’t need it in syntax candy, just make it simple

Use defineProps, defineEmits, defineExpose

DefineProps specifies the current props type, and the props object in the context needs a reference to props[key] in script. Template can call the key directly

2. Use defineEmits to specify that the trigger event contained in the current component is emitted through context emit returned by defineEmits

The defineExpose component exposes its own properties, which are available in the parent component.

<script setup> const props = defineProps({ foo: String,}) const emit = defineEmits(['change', 'goBack']) const name = "lee" // Expose({name}) </script>Copy the code

Await syntax support

We can use await syntax directly within script Setup:

<script setup>
    const data = await fetch(`/api/getUsers`).then((r) => r.json())
</script>
Copy the code

How do I get slots and attrs

Use useContext to get the context, and useContext gets the setup context

<script setup>
  import { useContext } from 'vue'
​
  const { slots, attrs } = useContext()
</script>
Copy the code

😈Pay attention to avoid pits:

  • 1. You cannot use this in setup. Why is that?

    This should be avoided in Setup because it will not find examples of components, unlike VUe2. Setup calls occur before data property\computed\methods are resolved, so they cannot be obtained in SETUP

  • DefineProps, defineEmits, defineExpose do not need to be introduced, vue3 single component internal automatic exposure API

  • 3. Setup can be used by importing components directly instead of registering them as in VUe2

Vue TSX composite support

The.jsx and.tsx files also work out of the box. Vue users should use the official @Vitejs/plugin-VUE-jsx plug-in, which provides support for Vue 3 features, including HMR, global component resolution, directives and slots.

✔ installation

npm i @vitejs/plugin-vue-jsx -D
Copy the code

➤ Introduced in late.config. ts, use the TSX support plug-in

import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import vueJsx from "@vitejs/plugin-vue-jsx" import { resolve } from "path"; import styleImport, { VantResolve } from 'vite-plugin-style-import'; import { viteMockServe } from "vite-plugin-mock"; export default defineConfig({ resolve: { alias: { "@": resolve(__dirname, "src"), comps: resolve(__dirname, "src/components"), apis: resolve(__dirname, "src/apis"), views: resolve(__dirname, "src/views"), utils: resolve(__dirname, "src/utils"), routes: resolve(__dirname, "src/routes"), styles: resolve(__dirname, "src/styles"), }, }, plugins: [ vue(), vueJsx(), styleImport({ resolves: [VantResolve()], }), viteMockServe({ mockPath: Mock ", // ↓ Parse the mock folder supportTs: false, // open the mock folder supportTs: false, // open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false, // Open the mock folder supportTs: false. Network: use --host to expose // port: 4000, // proxy: {// "^/ API ": {// target: "https://baidu.com", // changeOrigin: true, // ws: true, // rewrite: PathStr = > pathStr. Replace (/ ^ / API /, ""), / /}, / /}, / / cors: true,}, * * * / services in the production of basic public path. * @default '/' */ base: "./", });Copy the code

➤ TSX Component: com.tsX

Create file name suffix. TSX

Example:

SRC \components\comp\index.module. SCSS

.helloWorld { h1 { text-shadow: 2px 4px #ccc; } button { border: none; outline: none; padding: 5px 20px; background: #8bc34a; border-radius: 5px; border: 2px solid #a5a4a4; cursor: pointer; }}Copy the code

SRC \components\comp\ comp.tsx

import { ref, defineComponent } from "vue"; import classes from "./index.module.scss"; export default defineComponent({ name: "Comp", props: { msg: { type: String, required: true, }, }, setup: props => { const count = ref(0); return () => ( <div class={classes.helloWorld}> <h1>{props.msg}</h1> <button onClick={() => { count.value++; {count. Value} </button> </div>); }});Copy the code

The third step is introduced in the related components

<script setup lang="ts"> import Comp from './comp/Comp' ... </script> <template> <h1>{{showCount}}</h1> <button type="button" @click="addBtn"> </button> <van-button </van-button> <Comp MSG ="HelloWord Comp"> </Comp> </template> <style scoped> </style>Copy the code

😈Pay attention to avoid pits:

1, all vUE events do not apply: such as.self.stop. Prevent, etc

2. V-for is not applicable: Use map traversal instead of V-FOR

3. V-if not applicable: Use the ternary operator instead of v-if

Response formula of Vue3

  • Core:

    • Through Proxy(Proxy): intercept any (13) operation of any data attribute, including reading and writing of attribute value, adding attribute, deleting attribute, etc..

    • Reflect: Dynamically performs a specific action on the corresponding property of the proxied object

    • Documents:

      • Developer.mozilla.org/zh-CN/docs/…
      • Developer.mozilla.org/zh-CN/docs/…
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Initial-scale =1.0"> <title>Proxy and Reflect</title> </head> <body> <script> const user = {name: "John", age: 12}; /* const proxyUser = new Proxy(user, {get(target, Prop) {console.log(' hijack get()', prop) return reflect. get(target, prop)}, set(target, prop, Val) {console.log(' hijack set()', prop, val) return reflect. set(target, prop, val); // (2)}, deleteProperty(target, prop) {console.log(' hijack delete property ', prop) return reflect.deleteProperty (target, prop) prop) } }); Console. log(proxyUser===user) console.log(proxyuser.name, Age = 13 console.log(user) // Add attribute proxyuser. sex = 'male' Console. log(user) // Delete attributes delete proxyuser.sex console.log(user) </script> </body> </ HTML >Copy the code

Custom hook functions

  • Reusable functional functions encapsulated using Vue3’s composite API
  • Custom hooks function similar to the mixin technology in VUe2
  • The advantage of custom hooks: it is clear where the reusable functional code is coming from and easier to understand

Example 1

src\hooks/useMousePosition.ts

import { ref, onMounted, OnUnmounted} from 'vue' // export default function useMousePosition () {const x = ref(-1) Const y = ref(-1) // Const updatePosition = (e: MouseEvent) = > {x.v alue = e.p ageX y.v alue = e.p ageY excuse} / / mount binding after clicking to monitor onMounted (() = > {document. AddEventListener (' click ', UpdatePosition)}) / / unloading unbundling before clicking to monitor onUnmounted (() = > {document. The removeEventListener (' click ', updatePosition) }) return {x, y} }Copy the code

In the component

<script setup lang="ts"> import { computed, ref } from 'vue' import { useStore } from '@/store/index'; import http from '.. /utils/server' import Comp from './comp/Comp' import useMousePosition from '@/hooks/useMousePosition' const store = useStore() const count = ref(0) const showCount = computed(() => { return store.getters['getCount'] }) const {x, y} = useMousePosition() const addBtn = () => { store.commit('setCount', ++count.value) } // fetch("/api/getUsers") // .then( response => { // return response.json() // }) // .then(data => { //  console.log('/api/getUsers',data) // }) // try { // let data = await http.get({url:"/getUsers"}) // console.log(data,'data') // } catch (error) { // console.log(error,'error') // } </script> <template> <h1>{{ showCount }}</h1> <div class="show-mouse-box"> Use /hooks/useMousePosition: x: {{x}}, y: {{y}}</div> <br> <button type="button" @click="addBtn"> </button> <van-button type="success" > </van-button> <Comp </Comp> </template> <style scoped>. Show-mouse-box {font-size: 14px; } </style>Copy the code

Click to get different x and Y mouse coordinates

Ref, toRefs, reactive

ref

  • Function: Defines a response to data

  • Const XXX = ref(initValue):

    • Create a reference object that contains responsive data
    • Js operation data: xxx.value
    • To manipulate data in a template:.value is not required
  • Typically used to define a basic type of responsive data

Ref fetch element

Use the ref function to get the label elements in the component

The sample

<script setup lang="ts"> import {onMounted, ref} from 'vue' /* ref Let the input box to automatically focus * / const inputRef = ref < HTMLElement | null > (null) onMounted (() = > {inputRef. Value & & inputRef. Value. The focus ()})  } </script> <template> <h2>App</h2> <input type="text">--- <input type="text" ref="inputRef"> </template>Copy the code

toRefs

Convert a reactive object to a normal object whose property is a ref

Application: toRefs is useful when returning a reactive object from a synthesized function so that the consuming component can decompose the returned object without losing the reactive

Question time

🙋 Q: All attribute values fetched by reactive objects are non-reactive

A: toRefs allows you to convert all raw properties of a reactive object to reactive REF properties

reactive

  • Function: Defines a response for multiple data
  • Const proxy = Reactive (obj): a reactive proxy object that receives a common object and then returns that common object
  • Reactive transformations are “deep” : they affect all nested properties inside the object
  • Internal es6-based Proxy implementation, through the Proxy object operation source object internal data is responsive

☞ point: typescript

Because there are too many typescript knowledge points to write about, the length is already too long. We will write a detailed explanation of typescript later. This side is about understanding.

The characteristics of the TypeScript

TypeScript has three main features:

  • It starts with JavaScript and ends with JavaScript

TypeScript compiles clean, concise JavaScript code and runs in any browser, Node.js environment, and any JavaScript engine that supports ECMAScript 3 (or later).

  • Powerful type system

The type system allows JavaScript developers to use efficient development tools and common operations such as static checking and code refactoring when developing JavaScript applications.

  • Advanced JavaScript

TypeScript offers the latest and evolving JavaScript features, including those from ECMAScript 2015 and future proposals, such as asynchronous functionality and Decorators, to help build robust components.

TypeScript integration

If we did not choose vuE-TS when we installed the framework earlier, we would like to switch to TS

✔ installation

npm install -g typescript
Copy the code

After the installation, run the following command on the console to check whether the installation is successful:

tsc -V 
Copy the code

✔ Ts file can also be imported directly in the SFC by

Example: Create a component using TS

<script lang="ts"> import { defineComponent } from 'vue' interface Course { id: number; name: string; } export default defineComponent({ setup() { const state = ref<Course[]>([]); SetTimeout (() => {state.value.push({id: 1, name: "full stack architect"}); }, 1000); }}); </script>Copy the code

Ts reference configuration, tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "baseUrl": ".",
    "paths": {
      "@/*":["src/*"],
      "utils": ["src/utils/*"] ,
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "mock/test.ts"],
  "exclude": ["node_modules"]
}
​
Copy the code