生活札记

Vue3学习笔记 - 高阶(三)

copylian    1 评论    13618 浏览    2022.06.01

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

教程:https://www.bilibili.com/video/BV1su411D7GV

参考:https://blog.csdn.net/weixin_43931876/article/details/120058286


1、TypeScript(JavaScript超集):

1)、https://www.tslang.cn/

2)、https://www.typescriptlang.org/zh/


2、安装TypeScript

1)、下载安装nodejs

2)、npm镜像改为国内:

    npm get registry

    npm config set registry=https://registry.npm.taobao.org/

    或者安装cnpm

    npm install -g cnpm --registry=https://registry.npm.taobao.org/

3)、安装typescript:npm install -g typescript@latest

4)、查看版本:tsc -v

5)、安装ts-node(运行ts):npm install -g ts-node


3、TypeScript变量申明、变量类型:

// 变量声明

let num:number = 100

num = 200

console.log(num)


// 变量自动推断

let num2 = 300

console.log(num2)


// 变量声明

let stringA:string = "飓风呀"

stringA = "哈哈哈"

console.log(stringA)


// 函数变量声明

function count(a:number, b:number) {

    return a+b

}

console.log(count(1, 2))


4、TypeScript类型:

// 类型

// 1、boolean(布尔)、string(字符串)、number(数字)、array(数组)

// 2、null(null不存在)、undefined(定义了未初始化)、any(任意)、unknown(另一个any)

// 3、tuple(元组,类似数组)、void(没有任何类型)、never(永不存在)、enum(枚举)


// boolean

let isshow:boolean = true

if (isshow) {

    console.log("true")

}


// string

let a:string = "飓风呀"


// number

let b:number = 1


// Array

let arr:number[]

arr = [1,2,3]


// 字面类型组合类型

let c:100|200

c = 200


let d:number|string

d = 100

d = "飓风呀"


// any、unknown

let e:any

e = 100

e = "飓风呀"


let f:unknown

f = 10

f = "飓风呀"


// array、object

let g:number[]

g = [1,2,3]


let h:Array<string>

h = ["1","2"]


// let i:object

let i = {

    username:"飓风呀",

    age:28

}


// 对象解构

let { username, age} = i

console.log(username, age)


// 展开运算符号...

let j = {

    ...i,

    sex:"男"

}

console.log(j)


// void、never:void代表返回空,never不会有返回

// void限定返回返回null、undefined

// never 类似无限循环或者报错

function testvoid(a:number):void {

    console.log(a)

    return undefined

}

testvoid(1)


function testnever(a:number):never {

    // 函数不结束,死循环

    while (true) {

        

    }


    // 抛出异常

    throw new Error("错误")

}


// tuple 元组

let k:[number,string,boolean,number]

k = [1,"2",true,3]


// ?代表可选,前面是必选,可选后面不能跟着必选

let l: [number, string, boolean?]

l = [1, "2", true]


l.push("aaa") // tuple操作与数组类型

console.log(l)


// enum 各种情况的语义化

enum m {

    ma = 0,

    mb = 1,

    mc = 2,

    md = "飓风呀"

}


// 常数枚举,会被隐藏

const enum n {

    ma = 0,

    mb = 1,

    mc = 2,

    md = "飓风呀"

}


// 类型别名(自定义类型,可以设置为联合类型)

type mytype = string|number

let o:mytype

o = "aaa"

o = 100


5、TypeScript面向对象:


// 类、面向对象(与PHP的面向对象有点类似)

abstract class Person {

    // 属性

    public name:string // 公有属性

    protected age:number // 保护属性

    private sex:string // 私有属性

    static job:string // 静态属性


    // 构造函数

    constructor(name:string, age:number, sex:string, job:string) {

        this.name = name

        this.age = age

        this.sex = sex

        Person.job = job // 静态无法用this获取

    }


    // 方法

    move():void{

        console.log("姓名:" + this.name + ",年龄:" + this.age + ",性别:" + this.sex + ",工作:" + Person.job)

    }

}


// extends 继承

class User extends Person {


    // 类内属性

    public girlfriend:string

    

    // 类内构造函数

    constructor(name: string, age: number, sex: string, job: string, girlfriend:string) {

        // 执行父类构造函数

        super(name, age, sex, job)


        // 类内属性

        this.girlfriend = girlfriend

    }


    // 重写方法

    move(){

        console.log("女朋友是:" + this.girlfriend)


        // 执行父类方法

        super.move()

    }


    // 自定义方法

    biaobai(){

        console.log("跟:" + this.girlfriend +",表白了啊")

    }

}


// 实例化 Person,如果类定义了 abstract(抽象类) 则不能直接实例化,只能被继承

// let person = new Person("飓风呀", 100, "女", "GO")

// person.move()


// 实例化 User

let user = new User("飓风呀",100,"女","GO","小王子")

user.biaobai()

user.move()


// interface 接口

interface Person2 {

    name:string

    move():void

}


// interface 接口继承必须严格重写接口里所有属性方法

class User2 implements Person2 {

    // 属性

    public name:string


    // 构造函数

    constructor(name:string){

        this.name = name

    }


    // 重写方法

    move():void{

        console.log(this.name)

    }

}


// 实例化 User2

let user2 = new User2("飓风呀");

user2.move()


6、TypeScript泛型


// 泛型

function funa<T,K>(name:T,age:K):T {

    console.log(name)

    console.log(age)

    return name

}

funa("飓风呀",100)

funa(100,"飓风呀")


// 类

class Person3<T,K> {

    // 属性

    name:T

    age:K


    // 构造函数

    constructor(name:T,age:K){

        this.name = name

        this.age = age

    }


    // 方法

    move():T{

        console.log(this.name + "" + this.age)

        return this.name

    }

}


// 实例化类

let person = new Person3("飓风呀", 100)

person.move()

let person2 = new Person3(100,"飓风呀")

person2.move()


7、tsconfig.json:ts编译配置

1)、初始化配置问:tsc --init

2)、编译:tsc -w

3)、配置文件:tsconfig.json

{

  // 包含

  "include":[

    "./src/*" // 编译src目录下所有文件

  ],


  // 排除

  "exclude": [

    "./exclude/*" // 排除exclude目录下所有

  ],


  // 文件

  "files": [

    "./02-type.ts"

  ],


  // 编译选项配置

  "compilerOptions": {

    /* Visit https://aka.ms/tsconfig to read more about this file */


    /* Projects */

    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */

    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */

    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */

    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */

    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */

    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */


    /* Language and Environment */

    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */

    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */

    // "jsx": "preserve",                                /* Specify what JSX code is generated. */

    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */

    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */

    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */

    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */

    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */

    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */

    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */

    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */

    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */


    /* Modules */

    "module": "commonjs",                                /* Specify what module code is generated. */

    // "rootDir": "./",                                  /* Specify the root folder within your source files. */

    // "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */

    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */

    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */

    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */

    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */

    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */

    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */

    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */

    // "resolveJsonModule": true,                        /* Enable importing .json files. */

    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */


    /* JavaScript Support */

    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */

    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */

    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */


    /* Emit */

    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */

    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */

    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */

    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */

    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */

    "outDir": "./dist",                                   /* Specify an output folder for all emitted files. */

    // "removeComments": true,                           /* Disable emitting comments. */

    // "noEmit": true,                                   /* Disable emitting files from a compilation. */

    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */

    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */

    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */

    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */

    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */

    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */

    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */

    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */

    // "newLine": "crlf",                                /* Set the newline character for emitting files. */

    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */

    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */

    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */

    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */

    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */

    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */


    /* Interop Constraints */

    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */

    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */

    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */

    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */

    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */


    /* Type Checking */

    "strict": true,                                      /* Enable all strict type-checking options. */

    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */

    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */

    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */

    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */

    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */

    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */

    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */

    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */

    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */

    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */

    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */

    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */

    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */

    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */

    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */

    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */

    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */

    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */


    /* Completeness */

    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */

    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */

  }

}


8、Vite:https://vitejs.cn/

1)、vite创建项目:npm create vite

2)、安装volar插件:Vue Language Features (Volar)、Volar代替vetur

3)、vite.config.ts配置文件:安装库包(node环境支持js):npm i @types/node --save-dev

import { defineConfig } from 'vite'

import vue from '@vitejs/plugin-vue'

import path from 'path'


// https://vitejs.dev/config/

export default defineConfig({

  // 插件

  plugins: [vue()],


  // 服务,启动之后变成 http://127.0.0.1:3001

  server:{

    port:3001

  },


  // 决定

  resolve:{

    // 别名

    alias:{

      "@":path.resolve(__dirname, "src"),

      "com":path.resolve(__dirname, "src/components")

    }

  }

})


模板导入路径简化:

// import HelloWorld from '@/components/HelloWorld.vue'

import HelloWorld from 'com/HelloWorld.vue


9、Setup语法糖:

1)、App.vue:

<script setup lange="ts">

// 每个组件都是独立的实例

import { ref, reactive, onMounted } from "vue"

import  SetupYes from "./views/SetupYes.vue"


// 常量

const title = ref("app")


// 对象

const obj = reactive({

  username:"飓风呀",

  age:[1,2,3,4]

})


// 方法

const parentClick = (val) => {

  alert(val)

}


// 获取ref子组件,名称必须与ref的值一致

let setupRef = ref(null)


// 子组件ref(TypeScript语法)

// const setupRef = ref<InstanceType<typeof SetupYes >>()



// 挂载

onMounted(() => {

  console.log(setupRef.value.mydata)

})

</script>


<template>

  <div>

    <h1>{{ title }} - {{ obj.username }}</h1>

  </div>

  <SetupYes msg="Hei Setup" :title="title" data-id="888" :ageArr="obj.age" @parentClick="parentClick" ref="setupRef">

    <template #header>

      <h2>我是slot插槽哈哈哈</h2>

    </template>

  </SetupYes>

</template>



2)、SetupYes.vue子组件:

<template>

    <div>

        <p>SetupYes</p>

        <p>属性msg:{{msg}}</p>

        <p>属性ageArr:{{ageArr}}</p>

        <p><button type="button" @click="clickEmits">点击Emit事件</button></p>

        <slot name="header">slottest</slot>

    </div>

</template>


<script setup>

import { ref, useSlots, useAttrs, onMounted } from "vue";

// defineProps:属性

// defineProps(

//     {

//         msg:{

//             type:String,

//             defult:"aaaa",

//             required:true

//         },

//         ageArr:{

//             type:Array,

//             defult(){

//                 return [10]

//             }

//         }

//     }

// )


// 默认值

const props = withDefaults(

    // 定义默认属性的类型 ? 表示可有可无

    defineProps<{

        msg?:string,

        // ageArr:[number]

        ageArr: Array<number>

    }>(),{

        // 默认值

        msg:"aaaa",

        ageArr:() => [10]

    }

)


// defineEmits:事件

// const emits = defineEmits(["parentClick"])

const emits = defineEmits<

    {

        (e:"parentClick", data:string):void

    }

>()

const clickEmits = () => {

    emits("parentClick", "Hei Hello") // 这个emits与上面的定义的 emits 保持一致

}


// defineExpose:暴露属性

const mydata = ref(666)

defineExpose({ mydata })


// useSlots()、useAttrs():属性如果在defineProps定义了,那这里就不输出

const slots = useSlots()

const atrrs = useAttrs()

onMounted(() => {

    console.log(slots.header && slots.header()) // slots.header() 是个方法

    console.log(atrrs)

})

</script>


3)、toRefs

// reactive声明响应式数据,用于声明引用数据类型

const state = reactive({

    name: 'Jerry',

    sex: '男'

})


// 使用toRefs解构,template可直接使用{{name}}、{{sex}}

const {name, sex} = toRefs(state)


4)、watch:三个参数,1-属性方法,2-新值旧值,3-配置参数

// 监听count

watch(

    () => state.count,

    (newVal, oldVal) => {

        console.log(state.count)

        console.log(`watch监听变化前的数据:${oldVal}`)

        console.log(`watch监听变化后的数据:${newVal}`)

    },

    {

        immediate: true, // 立即执行

        deep: true // 深度监听

    }

)


5)、nextTick():

<template>

    <child ref='childRef'/>

</template>


<script setup>

    import { ref, nextTick } from 'vue'

    // 引入子组件

    import child from './child.vue'

    

    // 子组件ref(TypeScript语法)

    const childRef = ref<InstanceType<typeof child>>()

    

    // nextTick

    nextTick(() => {

        // 获取子组件name

        console.log(childRef.value.name)

        // 执行子组件方法

        childRef.value.changeName()

    })

</script>


6)、插槽slot:

子组件

<template>

    // 匿名插槽

    <slot/>


    // 具名插槽

    <slot name='title'/>


    // 作用域插槽

    <slot name="footer" :scope="state" />

</template>


<script setup>

    import { useSlots, reactive } from 'vue'

    const state = reactive({

        name: '张三',

        age: '25岁'

    })

    

    const slots = useSlots()

    // 匿名插槽使用情况

    const defaultSlot = reactive(slots.default && slots.default().length)

    console.log(defaultSlot) // 1

    

    // 具名插槽使用情况

    const titleSlot = reactive(slots.title && slots.title().length)

    console.log(titleSlot) // 3

</script>


父组件

<template>

    <child>

        // 匿名插槽

        <span>我是默认插槽</span>

        

        // 具名插槽

        <template #title>

            <h1>我是具名插槽</h1>

            <h1>我是具名插槽</h1>

            <h1>我是具名插槽</h1>

        </template>


        // 作用域插槽

        <template #footer="{ scope }">

            <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer>

        </template>

    </child> 

</template>


<script setup>

    // 引入子组件

    import child from './child.vue'

</script>


7)、路由useRoute和useRouter:

<script setup>

    import { useRoute, useRouter } from 'vue-router'

    // 必须先声明调用

    const route = useRoute()

    const router = useRouter()


    // 路由信息

    console.log(route.query)


    // 路由跳转

    router.push('/newPage')

</script>


8)、路由导航守卫:

<script setup>

    import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'

    // 添加一个导航守卫,在当前组件将要离开时触发。

    onBeforeRouteLeave((to, from, next) => {

        next()

    })

    

    // 添加一个导航守卫,在当前组件更新时触发。

    // 在当前路由改变,但是该组件被复用时调用。

    onBeforeRouteUpdate((to, from, next) => {

        next()

    })

</script>


9)、Vuex:*Vue3 中的Vuex不再提供辅助函数写法

<script setup>

    import { useStore } from 'vuex'

    import { key } from '../store/index'

    

    // 必须先声明调用

    const store = useStore(key)

    

    // 获取Vuex的state

    store.state.xxx

    

    // 触发mutations的方法

    store.commit('fnName')

    

    // 触发actions的方法

    store.dispatch('fnName')

    

    // 获取Getters

    store.getters.xxx

</script>


10)、Pinia:Pinia 正式成为 Vue 官方的状态库,意味着 Pinia 就是 Vuex 5:https://pinia.web3doc.top/

Pinia 的优点:

    1)、同时支持 Composition Api 和 Options api 的语法;

    2)、去掉 mutations ,只有 state 、getters 和 actions ;

    3)、不支持嵌套的模块,通过组合 store 来代替;

    4)、更完善的 Typescript 支持;

    5)、清晰、显式的代码拆分;


安装

# 使用 npm

npm install pinia


# 使用 yarn

yarn add pinia


main.js 引入

import App from './App.vue'

import { createApp } from 'vue'

import { createPinia } from 'pinia'


const app = createApp(App)

app.use(createPinia())

app.mount('#app')


配置 store.js

import { defineStore } from 'pinia'


// defineStore 调用后返回一个函数,调用该函数获得 Store 实体

export const useStore = defineStore({

    // id: 必须,在所有 Store 中唯一

    id: 'globalState',


    // state: 返回对象的函数

    state: () => ({

        count: 1,

        data: {

            name: 'Jerry',

            sex: '男'

        }

    }),


    // getter 第一个参数是 state,是当前的状态,也可以使用 this 获取状态

    // getter 中也可以访问其他的 getter,或者是其他的 Store

    getters: {

        // 通过 state 获取状态

        doubleCount: (state) => state.count * 2,

        // 通过 this 获取状态(注意this指向)

        tripleCount() {

            return this.count * 3

        }

    },


    actions: {

        updateData (newData, count) {

            this.data = { ...newData }

            this.count = count

        

            // 使用 $patch 修改多个值

            this.$patch({

                data: { ...newData },

                count

            })

        }

    }

})


使用 store

<template>

    // 获取 store 的 state

    <p>姓名:{{store.data.name}}</p>

    <p>性别:{{store.data.sex}}</p>

    

    // 调用 actions方法 / 修改 store

    <button @click='update'>修改用户信息</button>

    

    // 获取 getter

    <p>获取getter:{{store.doubleCount}}</p>

</template>


<script setup>

    import { useStore } from '@store/store.js'

    const store = useStore()

    

    function update () {

        // 通过 actions 定义的方法修改 state

        store.updateData({ name: 'Tom', sex: '女' })

        

        // 通过 store 直接修改

        store.data = { name: 'Tom', sex: '女' }

        

        // 同时改变多个状态

        store.$patch((state) => {

            state.data = { name: 'Tom', sex: '女' }

            state.count = 2

        })

    }

</script>


其他方法

替换整个 state

$state 可以让你通过将 store 的属性设置为新对象来替换 store 的整个 state

const store = useStore()

store.$state = {

    name: 'Bob',

    sex: '男'

}


重置状态

调用 store 上的 $reset() 方法将状态重置为初始值

const store = useStore()

store.$reset()


11)、provide和inject: 


父组件

<template>

    <child/>

</template>


<script setup>

    import { ref, watch, provide } from 'vue'

    // 引入子组件

    import child from './child.vue'

    

    let name = ref('Jerry')

    // 声明provide

    provide('provideState', {

        name,

        changeName: () => {

            name.value = 'Tom'

        }

    })

    

    // 监听name改变

    watch(name, () => {

        console.log(`name变成了${name}`)

        setTimeout(() => {

            console.log(name.value) // Tom

        }, 1000)

    })

</script>


子组件

<script setup>

    import { inject } from 'vue'

    // 注入

    const provideState = inject('provideState')

    // 子组件触发name改变

    provideState.changeName()

</script>


12)、Vue3:Typescript与组合式API、defineProps、defineEmits等使用: https://blog.csdn.net/qq_14818715/article/details/128265658


10、简单项目:vue3.2+setup语法糖+ts+elementPlus+vue-router+vuex

教程:https://www.bilibili.com/video/BV1Su411q71n

安装:

1)、安装vite:npm create vite,选择vuets

2)、node环境支持js:npm install @types/node --save-dev

3)、vue-router:npm install vue-router@next

4)、vuex:npm install vuex@next --save

5)、 element-plus:npm install element-plus --save,加载方式https://element-plus.gitee.io/zh-CN/guide/quickstart.html

6)、sass(css):npm install sass-loader sass -D

7)、vscode自定义快捷模板:文件 >> 首选项 >> 配置用户代码片段

8)、element-plus全局图标:npm install @element-plus/icons-vue

只袄早~~~
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!

文明上网理性发言!