# Vue3
# 1.Vue3的优势
1.更容易维护 组合式API 更好的typeScript支持
2.更快的速度 重写diff算法 模板编译优化 更高效的组件初始化
3.更小的体积 良好的TreeShaking 按需引入
4.更优的数据响应式 Proxy
1
2
3
4
2
3
4
# 2.create-vue
create-vue 是Vue官方新的脚手架工具 底层切换到了Vite(下一代构建工具) 为开发提供极速响应
// Vue-cli 底层 webpack
// create-vue 底层 vite
1
2
3
2
3
# 3.创建项目
1.前提环境条件:
node版本 大于16.0
node -v 查看版本
2.创建Vue应用
npm create vue@latest
npm init vue@latest
(安装并执行create-vue)
3.Vue3 插件:
volar
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 4.组合式API-setup
<!-- 加上setup允许在script中直接编写组合式API -->
<script>
export default {
// 1.执行时机比beforeCreate早
// 2.获取不到this this=undefined
// 3.数据和函数 需要在setup中return 才能在模板中使用
setup() {
console.log('setup函数');
console.log(this);
// 函数
const logMessage = () => {
console.log('message');
}
// 数据
const msg = 'hello world'
return {
msg,
logMessage
}
},
beforeCreate() {
console.log('beforeCreate函数');
console.log(this);
}
}
</script>
<template>
<!-- 不再要求唯一根元素 -->
<div>学习Vue3</div>
<div>{{ msg }}</div>
<button @click="logMessage">按钮</button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 5.setup语法糖写法
<!-- 语法糖写法 -->
<script setup>
const message = 'hello world'
const logMessage = () => {
console.log('message: ' + message);
}
</script>
<template>
<div>
{{ message }}
<button @click="logMessage">点击我</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 6.setup总结
1.setup选项的执行时机?
最早的 比beforeCrete早
2.setup写代码的特点是什么?
定义数据 + 函数 然后以对象的方式return
3.<script setup> 解决了什么问题?
经过语法糖的封装更简单的使用组合式API (不用再以对象的方式return)
4.setup中的this还指向组件实例吗?
this=undefined
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 7.reactive()
作用:接受对象类型数据的参数传入并返回一个响应式的对象
<!-- 语法糖写法 -->
<script setup>
// reactive:接收一个对象类型的数据 返回一个响应式的对象
import { reactive } from 'vue';
const state = reactive({
count: 100,
})
console.log(state.count); // 100
const setCount = () => {
state.count++
}
</script>
<template>
<div>
{{ state.count }}
<button @click="setCount">+</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 8.ref()
推荐: 以后声明数据 统一用ref
<script setup>
作用:可以接收简单数据类型 和 对象数据类型 传入并返回一个响应式对象
// ref:接收简单数据类型和复杂数据类型 返回一个响应式对象
// 本质:是在原有传入数据的基础上 外层包了一层对象 包成了复杂类型
// 底层:包成复杂类型之后 再借助reactive实现的响应式
// script中访问数据需要通过 .value
// template中访问数据需要通过 不需要加.value
const number = ref(1)
console.log(number.value); // 1
const setNumber = () => {
number.value++
}
</script>
<template>
<div>
<h1>reactive写法</h1>
{{ state.count }}
<button @click="setCount">+</button>
<hr>
<h1>ref写法</h1>
{{ number }}
<button @click="setNumber">+</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 9.reactive() 和 ref() 总结
1.reactive()和ref()的共同作用是什么?
用函数调用的方式生成响应式数据 将数据变成响应式数据
2.reactive vs ref?
reactive不能处理简单的数据类型
ref参数类型支持更好但必须通过.value访问修改
ref函数的内部实现依赖于reactive函数
3.在实际工作中 推荐使用 ref 统一编码规范
1
2
3
4
5
6
7
2
3
4
5
6
7
# 10.组合式API-computed
计算属性基本思想和Vue2的完全一致 组合式API下的计算属性只是修改了写法
<script setup>
import { computed, ref } from 'vue';
const arr = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
// 计算属性
const computedArr = computed(() => {
return arr.value.filter((item) => item > 5)
})
// 修改数组的方法
const updatedArr = () => {
arr.value.push(11)
}
// 定义可读可写 computed
const computedTest = computed({
get: () => {
return arr.value
},
set: (value) => {
return arr.value = value
}
})
console.log(computedTest.value);
const setArr = () => {
computedTest.value = [1]
}
</script>
<template>
<div>{{ arr }}</div>
<div>{{ computedArr }}</div>
<button @click="updatedArr">+</button>
<div>{{ computedTest }}</div>
<button @click="setArr">修改</button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 11.computed总结
1.计算属性中不应该有副作用
不应该有 比如异步请求 操作dom
2.避免直接修改计算属性值
计算属性应该是只读的 特殊情况可以配置get set
1
2
3
4
2
3
4
# 12.组合式API-watch函数
作用:侦听一个或多个数据的变化 数据变化时立即执行回调函数
1.immediate(立即执行) 2.deep(深度监听)
1
2
2
# 1.监听单个数据
<script setup>
import { ref, watch } from 'vue';
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue);
})
setInterval(() => {
count.value++
}, 1000)
</script>
<template>
<div>{{ count }}</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2.监听多个数据
<script setup>
import { ref, watch } from 'vue';
const count = ref(0)
const number = ref(1)
// 监听单个数据
// watch(count, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// })
// 监听多个数据
watch([count, number], ([newCount, newNumber], [oldCount, oldNumber]) => {
console.log(newCount, newNumber);
console.log(oldCount, oldNumber);
})
setTimeout(() => {
count.value++
number.value++
}, 1000)
</script>
<template>
<div>{{ count }}</div>
<div>{{ number }}</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3.immediate 立即执行
<script setup>
import { ref, watch } from 'vue';
const count = ref(0)
// 监听单个数据
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue);
}, {
immediate: true // 立即执行
})
</script>
<template>
<div>{{ count }}</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 4.deep 深度监视
默认watch 进行的是浅层的监视(修改了对象的地址才能监视到)
const ref1 = ref(简单数据类型) 可以直接监视
const ref2 = ref(复杂类型) 默认watch监视不到复杂类型内部数据的变化
<script setup>
import { ref, watch } from 'vue';
const info = ref({
name: '小明',
age: 12,
sex: '男'
})
const setAge = () => {
info.value.age++
}
// 深度监听 对象数据
watch(info, (newValue) => {
console.log(newValue)
}, {
deep: true
})
</script>
<template>
<div>
{{ info.name }}
{{ info.age }}
{{ info.sex }}
<button @click="setAge">age++</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 4.精确监听对象的某个属性
在不开启deep的前提下 侦听age的变化 只有age变化时才执行回调
<script setup>
import { ref, watch } from 'vue';
const info = ref({
name: '小明',
age: 12,
sex: '男'
})
const setAge = () => {
info.value.age++
}
// 精确侦听某个属性
watch(
() => info.value.age,
(newValue) => {
console.log(newValue);
}
)
</script>
<template>
<div>
{{ info.name }}
{{ info.age }}
{{ info.sex }}
<button @click="setAge">age++</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 13.watch 总结
1.作为watch函数的第一个参数 ref对象需要添加.value吗?
不需要 第一个参数就是传入ref对象
2.watch只能侦听单个数据吗?
单个或多个
3.不开启deep 直接监视复杂类型 修改属性能触发回调吗?
不能 默认是浅层监听
4.不开启deep 如何精确侦听对象的某个属性?
// 精确侦听某个属性
watch(
() => info.value.age,
(newValue) => {
console.log(newValue);
}
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 14.生命周期
<script setup>
import { onMounted } from 'vue';
// beforeCrate 和 created 的相关代码
// 一律放在 setup 中执行
const getList = () => {
setTimeout(() => {
console.log('发送请求 获取数据');
}, 2000);
}
// 一进入页面的请求
getList()
// 如果有些代码 需要在mounted生命周期中执行
onMounted(() => {
console.log('mounted生命周期函数1');
})
onMounted(() => {
console.log('mounted生命周期函数2');
})
</script>
<template>
<div></div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 15.组合式API-父传子
1.基本思想
父组件中给子组件绑定属性
子组件内部通过props选项接收
1
2
3
2
3
子组件
<script setup>
import { defineProps, defineOptions } from 'vue'
defineOptions({
name: "SonPage"
})
// 接收父组件的传来的数据 编译宏
const props = defineProps({
text: {
type: String,
default: ''
},
money: {
type: Number,
default: 0
}
})
console.log(props.text);
// 对于props 传递过来的数据 模板中可以直接使用 script中必须props.属性
</script>
<template>
<div>子组件接收到的父组件的数据:{{ text }}--{{ money }}</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
父组件
<script setup>
import { ref } from 'vue'
// 局部组件 导入进直接使用
import sonVue from './components/son.vue';
const money = ref(100)
const getMoney = () => {
money.value++
}
</script>
<template>
<div>
<button @click="getMoney">挣钱</button>
<!-- 给子组件传值 -->
<sonVue text="大家好" :money="money"></sonVue>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 16.组合式API-子传父
1.基本思想
父组件中给子组件标签通过@绑定事件
子组件内部通过emit方法触发事件
1
2
3
2
3
子组件
<script setup>
import { defineProps, defineOptions } from 'vue'
defineOptions({
name: "SonPage"
})
// 向父组件传递值
const emit = defineEmits(['sub-money'])
const spend = () => {
emit('sub-money', 10) // 子组件触发 父组件监听的事件
}
</script>
<template>
<button @click="spend">花钱</button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
父组件
<script setup>
import { ref } from 'vue'
// 局部组件 导入进直接使用
import sonVue from './components/son.vue';
const money = ref(100)
const subMoeny = (value) => {
money.value -= value
}
</script>
<template>
<div>
<!-- 给子组件传值 -->
<sonVue text="大家好" :money="money" @sub-money="subMoeny"></sonVue>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 17.组件通信 总结
父传子
1.父传子的过程中通过什么方式接收props?
defineProps({属性名:类型})
2.setup语法糖中如何使用父组件传来的数据?
const props = defineProps({属性名:类型})
props.xxx
子组件
1.子传父的过程中通过什么方式得到emit方法?
defineEmits(['事件名称'])
2.怎么触发事件
emit('事件名称','传递的参数值')
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 18.组合式API-模板引用
<script setup>
import { ref } from 'vue';
import InputPageVue from './components/InputPage.vue';
// 1.创建 一个ref对象 通过inputRef.value 可以访问到绑定的元素
const inputRef = ref(null)
const inputVue = ref(null)
const focus = () => {
inputRef.value.focus()
}
const ClickFn = () => {
// 因为子组件使用defineExpose暴露出来了 属性和 方法 所以可以直接访问
inputVue.value.sayHi()
}
</script>
<template>
<div>
<div>
<!-- 绑定ref -->
<input ref="inputRef" type="text">
<button @click="focus">点击让输入框聚焦</button>
</div>
<InputPageVue ref="inputVue"></InputPageVue>
<button @click="ClickFn">获取组件</button>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 19.defineExpose()
在默认情况下 script setup语法糖下组件内部的属性和方法是不开放给父组件访问的
可以通过defineExpose()编译宏指定哪些属性和方法允许被访问
<script setup>
defineOptions({
name: 'InputPage'
})
const count = 999
const sayHi = () => {
console.log('sayHi');
}
// 暴露出去数据
defineExpose({
count,
sayHi
})
</script>
<template>
<div>
我是用于测试的组件 - {{ count }}
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 20.模板引用总结
1.获取模板引用的时机是什么时候?
组件挂载完毕 OnMonted
2.defineExpose编译宏的作用是什么?
指定哪些属性和方法可以被父组件访问调用
1
2
3
4
2
3
4
# 21.组合式API-provide和inject
作用和场景
·顶层组件向任意的底层组件传递数据和方法 实现跨层组件通信
1.顶层组件通过provide函数提供数据
2.底层组件通过inject函数获取数据
provide('key',顶层组件中的数据)
const message = inject('key')
1
2
3
4
5
6
7
2
3
4
5
6
7
# 22.Vue3.3新特性-defineOptions
<script setup>
import { defineOptions } from 'vue';
defineOptions({
name: 'App'
})
</script>
<template>
<div></div>
</template>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 23.Vue3.3新特性-defineModel
// Vue2中 v-model原理是 value 和 input
// Vue3中 v-model原理是 modelValue 和 update:modelValue
1
2
2
# 1.不使用defineModel
父组件
<script setup>
import MyInputVue from '@/components/MyInput.vue'
import { ref } from 'vue';
const text = ref('123')
</script>
<template>
<div>
<MyInputVue v-model="text"></MyInputVue>
{{ text }}
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
子组件
<script setup>
defineProps({
modelValue: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue'])
const onInput = (e) => {
console.log(e.target.value); // 获取到输入框输入的值
emit('update:modelValue', e.target.value) // 触发事件 更改父组件的值
}
</script>
<template>
<div>
<h1>Hello World!</h1>
<input type="text" :value="modelValue" @input="onInput">
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.使用defineModel
让这个生效 先在vite.config.js中开启
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
script: {
defineModel: true, // 开启
},
}),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
父组件
<script setup>
import MyInputVue from '@/components/MyInput.vue'
import { ref } from 'vue';
const text = ref('123')
</script>
<template>
<div>
<MyInputVue v-model="text"></MyInputVue>
{{ text }}
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
子组件
<script setup>
import { defineModel } from 'vue';
const modelValue = defineModel()
</script>
<template>
<div>
<input type="text" :value="modelValue" @input="e => modelValue = e.target.value">
</div>
</template>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 24.Vue3最新状态管理工具-pinna
1.提供了更加简单的API(去掉了mutations)
2.提供符合 组合式风格的API (和Vue3新语法统一)
3.去掉了modules的概念 每个store都是一个独立的模块
4.配色ts 更加友好 提供可靠的类型推断
1
2
3
4
2
3
4
# 1.手动添加pinia到Vue项目
1.使用vite此次创建一个空的Vue3项目
npm create vue@latest
2.按照官方文档安装pinia到项目中
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 2.基本使用
在 Setup Store 中:
ref()就是state属性computed()就是gettersfunction()就是actions
创建仓库 ./store/counter.js
import { defineStore } from "pinia";
import { ref } from "vue";
// 定义store
// 参数一:仓库的唯一标识
export const useCounterStore = defineStore("counter", () => {
// 声明数据 state
const count = ref(10);
// 声明操作数据的方法 actions function
const double = function(){
count.value = count.value * 2;
}
// 声明基于数据派生的方法 getters computed
const message = ref("counter");
// 返回数据
return {
count,
message,
double
};
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
使用数据
<script setup>
// 引入仓库
import { useCounterStore } from './store/counter';
import Son1ComVue from './components/Son1Com.vue';
import Son2ComVue from './components/Son2Com.vue';
const counterStore = useCounterStore()
console.log(counterStore.count); // 获取数据
</script>
<template>
<div>App.vue根组件 - {{ counterStore.count }}</div>
<Son1ComVue />
<Son2ComVue />
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.发起异步请求
仓库代码
import axios from "axios";
import { defineStore } from "pinia";
import { ref } from "vue";
// 定义一个仓库
export const useChannelStore = defineStore("channel", () => {
// 声明数据
const channelList = ref([]);
const getList = async () => {
const {
data: { data },
} = await axios.get("http://geek.itheima.net/v1_0/channels");
channelList.value = data.channels;
console.log(data.channels);
};
// 必须返回
return {
channelList,
getList,
};
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
使用仓库
<script setup>
import { useCounterStore } from './store/counter';
import Son1ComVue from './components/Son1Com.vue';
import Son2ComVue from './components/Son2Com.vue';
const counterStore = useCounterStore()
console.log(counterStore.count); // 获取数据
// 使用仓库
import { useChannelStore } from './store/channel'
const channelStore = useChannelStore()
channelStore.getList()
</script>
<template>
<div>App.vue根组件 - {{ counterStore.count }} - {{ counterStore.message }} - {{ counterStore.double }}</div>
<Son1ComVue />
<Son2ComVue />
<ul>
<li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 4.storeToRefs 恢复数据响应式
state 不能直接解构
actions 可以直接解构
getters 可以直接解构
<script setup>
import { useCounterStore } from './store/counter';
import { storeToRefs } from 'pinia'
import Son1ComVue from './components/Son1Com.vue';
import Son2ComVue from './components/Son2Com.vue';
const counterStore = useCounterStore()
console.log(counterStore.count); // 获取数据
// 直接解构会导致数据不是响应式的 使用storeToRefs() 恢复数据的响应式
const { count, message } = storeToRefs(counterStore)
import { useChannelStore } from './store/channel'
const channelStore = useChannelStore()
channelStore.getList()
</script>
<template>
<div>App.vue根组件 - {{ count }} - {{ message }} - {{ counterStore.double }}</div>
<Son1ComVue />
<Son2ComVue />
<ul>
<li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 5.pinia 持久化
https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/ 官网
安装插件
npm i pinia-plugin-persistedstate
1
main.js
import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";
// 引入pinia持久化插件
import { piniaPluginPersistedstate } from "pinia-plugin-persistedstate";
const pinia = createPinia(); // 创建pinia 实例
pinia.use(piniaPluginPersistedstate); // pinia 使用插件
const app = createApp(App); // 创建根实例
app.use(pinia); // pinia插件的安装
app.mount("#app"); // app实例的挂载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
用法
创建 Store 时,将 persist 选项设置为 true。
import { defineStore } from 'pinia'
export const useStore = defineStore(
'main',
() => {
const someState = ref('你好 pinia')
return { someState }
},
{
persist: true, // 开启持久化存储
},
)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
自定义key
自定义配置 https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html
import { defineStore } from "pinia";
import { computed, ref } from "vue";
// 定义store
// 参数一:仓库的唯一标识
export const useCounterStore = defineStore(
"counter",
() => {
// 声明数据 state
const count = ref(10);
// 声明操作数据的方法 actions function
const sub = function () {
count.value--;
};
const add = function () {
count.value++;
};
// 声明基于数据派生的方法 getters computed
const double = computed(() => {
return count.value * 2;
});
const message = ref("counter");
return {
count,
message,
add,
sub,
double,
};
},
{
persist: {
key: "counterStore", // 指定key
paths:['count'] // 指定对count进行持久化
}, // 开启当前模块持久化
}
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 6.pinia总结
1.pinia是用来做什么的?
新一代的状态管理工具 替代vuex
2.pinia还需要mutations?
不需要 actions 支持同步和异步
3.pinia如何实现getter?
通过computed实现
4.pinia产生的Store如何解构赋值数据保持响应式?
storeToRefs
5.Pinia如何快速实现持久化?
pinia-plugin-persistedstate
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 2.Vue3大事件项目管理系统
# 1.pnpm包 管理器
优势:比同类工具快两倍左右 节省磁盘空间
// 安装pnpm
npm install -g pnpm
// 创建项目
pnpm create vue
pnpm install
pnpm add axios
pnpm add axios -D
pnpm remove axios
pnpm dev
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11