一. 初始化项目
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