一. 初始化项目

1.按步骤提示初始化:

1
# pnpm pnpm create vite # npm npm init vite@latest # yarn yarn create vite

2.快速初始化(建议使用):

1
# pnpm pnpm create vite project-name -- --template vue-ts # npm 6.x npm init vite@latest project-name --template vue-ts   # npm 7+, 需要额外的双横线: npm init vite@latest project-name -- --template vue-ts   # yarn yarn create vite project-name --template vue-ts

注意:由于 vue3 和 vue2 配置不同,需要安装不同的应用插件

vue3 需要应用 volar 以下两个插件,禁用 vetur; vue2 需要应用 vetur 插件,禁用 volar

二. ref

小技巧: 控制台设置勾选 启用自定义格式设置工具(开启后 console.log ref 定义的值时可以直接在控制台打印出里面.value 的值)

三. reactive

不能直接赋值,否则会破环其响应式
解决方案 1:数组可以使用 push 加解构

1
2
3
4
5
6
7
8
import { reactive } from 'vue'
let person = reactive<number[]>([])
setTimeout(() => {
const arr = [1, 2, 3]
person.push(...arr)
console.log(person);

},1000

解决方案 2:包裹一层对象

1
2
3
4
5
6
7
8
9
10
11
12
type Person = {
list?:Array<number>
}
let person = reactive<Person>({
list:[]
})
setTimeout(() => {
const arr = [1, 2, 3]
person.list = arr;
console.log(person);

},1000)

四. toRef

toRef 只能修改响应式对象的值, 非响应式的数据视图毫无变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<button @click="change">按钮</button>
{{state}}
</div>
</template>

<script setup lang="ts">
import { reactive, toRef } from 'vue'

const obj = reactive({
foo: 1,
bar: 1
})

const state = toRef(obj, 'bar')

const change = () => {
state.value++
console.log(obj, state);

}
</script>

五. toRefs

1
2
3
4
5
6
7
8
9
10
import { reactive, toRefs } from 'vue'
const obj = reactive({
foo: 1,
bar: 1
})

let { foo, bar } = toRefs(obj)

foo.value++
console.log(foo, bar);

toRefs 的源码,其实就是一个循环 toRef

若你想使你定义的值结构出来式响应式的, 你必须用 toRefs 去解构,如果你是直接解构的话,结构出来的值是不具备响应式的(虽然它的数据打印出来变了,但是页面并不会变成最新的值)

六. toRaw

让你定义的响应式对象变成非响应式, 让响应式对象变成了一个原始对象,脱离了 proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
import { reactive, toRaw } from 'vue'

const obj = reactive({
foo: 1,
bar: 1
})

const state = toRaw(obj)
// 响应式对象转化为普通对象

const change = () => {
console.log(obj, state);
}

七. computed

1. 函数形式

1
2
3
4
5
6
7
8
import { computed, reactive, ref } from 'vue'
let price = ref(0)//$0

let m = computed<string>(()=>{
return `$` + price.value
})

price.value = 500

2. 对象形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>{{ mul }}</div>
<div @click="mul = 100">click</div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
let price = ref<number | string>(1)//$0
let mul = computed({
get: () => {
return price.value
},
set: (value) => {
price.value = 'set' + value
}
})
</script>

<style>
</style>

八. watch

1.监听 Ref 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { ref, watch } from 'vue'

let message = ref({
nav:{
bar:{
name:""
}
}
})

watch(message, (newVal, oldVal) => {
console.log('新的值----', newVal);
console.log('旧的值----', oldVal);
},{
immediate:true,
deep:true
})

监听多个 ref 注意变成数组啦

1
2
3
4
5
6
7
8
9
import { ref, watch ,reactive} from 'vue'

let message = ref('')
let message2 = ref('')

watch([message,message2], (newVal, oldVal) => {
console.log('新的值----', newVal);
console.log('旧的值----', oldVal);
})

监听 Reactive
使用 reactive 监听深层对象开启和不开启 deep 效果一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { ref, watch ,reactive} from 'vue'

let message = reactive({
nav:{
bar:{
name:""
}
}
})


watch(message, (newVal, oldVal) => {
console.log('新的值----', newVal);
console.log('旧的值----', oldVal);
})

案例 2 监听 reactive 单一值

1
2
3
4
5
6
7
8
9
10
11
import { ref, watch ,reactive} from 'vue'

let message = reactive({
name:"",
name2:""
})

watch(()=>message.name, (newVal, oldVal) => {
console.log('新的值----', newVal);
console.log('旧的值----', oldVal);
})

九. watchEffect 高级侦听器

watchEffect 一开始就会执行,而 watch 要加 immediate:true 才会在一开始就执行

立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
如果用到 message 就只会监听message 就是用到几个监听几个 而且是非惰性 会默认调用一次

1
2
3
4
5
6
let message = ref<string>('')
let message2 = ref<string>('')
watchEffect(() => {
//console.log('message', message.value);
console.log('message2', message2.value);
})

清除副作用

就是在触发监听之前会调用一个函数可以处理你的逻辑例如防抖

1
2
3
4
5
6
7
8
9
10
import { watchEffect, ref } from 'vue'
let message = ref<string>('')
let message2 = ref<string>('')
watchEffect((oninvalidate) => {
//console.log('message', message.value);
oninvalidate(()=>{

})
console.log('message2', message2.value);
})

停止跟踪 watchEffect 返回一个函数 调用之后将停止更新

1
2
3
4
5
6
7
8
9
10
11
12
13
const stop =  watchEffect((oninvalidate) => {
//console.log('message', message.value);
oninvalidate(()=>{

})
console.log('message2', message2.value);
},{
flush:"post",
onTrigger () {

}
})
stop()

更多的配置项

副作用刷新时机 flush 一般使用 post

pre sync post
更新时机 组件更新前执行 强制效果始终同步触发 组件更新后执行

onTrigger 可以帮助我们调试 watchEffect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { watchEffect, ref } from 'vue'
let message = ref<string>('')
let message2 = ref<string>('')
watchEffect((oninvalidate) => {
//console.log('message', message.value);
oninvalidate(()=>{

})
console.log('message2', message2.value);
},{
flush:"post",
onTrigger () {

}
})

十. 组件和生命周期

1.组件

组件: 在 vue3 中只需要引入组件,不需要像 vue2 一样在 conponents 里面进行注册

例如 helloWorld 充当子组件
父组件使用
引入子组件 helloWorld 然后直接就可以去当标签去使用 (切记组件名称不能与 html 元素标签名称一样)

2.生命周期

vue3 中 beforeCreate 和 created 不再需要

onBeforeMount()
在组件 DOM 实际渲染安装之前调用。在这一步中,根元素还不存在。
onMounted()
在组件的第一次渲染后调用,该元素现在可用,允许直接 DOM 访问
onBeforeUpdate()
数据更新时调用,发生在虚拟 DOM 打补丁之前。
onUpdated()
DOM 更新后,updated 的方法即会调用。
onBeforeUnmount()
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
onUnmounted()
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

选项式 API Hook inside setup
beforeCreate Not needed*
created Not needed*
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered
activated onActivated
deactivated onDeactivated