vue3 新特性
1、setup
setup是vue3定义的代码实现舞台。需要在模板中使用的变量和方法,需要return。
setup执行顺序在beforeCreat,并且在setup中this为undefined
setUp(props, contex)接受两个参数
props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性(其实就是vue2.0的props功能)
context:上下文对象(其中可以获取到1、attrs组件外部传递过来,但没有在props配置中声明的属性。2、slots:插槽内容3、emit:分发自定义事件的函数,并且以后在setup中不能写this.$emit,要写context.emit)
<template> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> <button @click="sayInfo">显示信息</button> </template> <script> export default { name: "App", setup(){ //此时的数据不具有双向绑定的功能 let name:string = "小明" let age:number = 18 // 方法 function sayInfo(){ alert(`你好${name},你太厉害了吧`) } // 想要在模板中使用setup中的方法或者数据,必须return return { name,age, sayInfo } // return ()=> h('h1','试试') } }; </script>
setup另外一种写法是直接写到script标签中:<script setup>
2、ref()
定义一个响应式的变量。let name:string = ref(‘test’)
js操作变量的方法是name.value,模板中直接{{name}}
<template> <h2>姓名:{{ name }}</h2> <h2>年龄:{{ age }}</h2> <button @click="changeInfo">修改信息</button> </template> <script> import { ref } from "vue"; export default { name: "App", setup() { // 数据 let name:string = ref("小明"); let age:number = ref(18); // 方法 function changeInfo() { name.value = "小明"; age.value = 48; } return { name, age, changeInfo, }; }, }; </script>
3、reactive()
用来定义响应式对象:let obj=reactive({a:1,b:2})
js操作方法是obj.a=2(不需要.value)
<template> <h2>姓名:{{ yk.name }}</h2> <h2>年龄:{{ yk.age }}</h2> <h2>爱好:{{ yk.hobby }}</h2> <h3>测试数据:{{ yk.job.a.b.c }}</h3> <button @click="changeInfo">修改信息</button> </template> <script> import { reactive } from "vue"; export default { name: "App", setup() { // 数据 let yk = reactive({ age: 18, hobby: ["吃饭", "睡觉", "打豆豆"], job: { a: { b: { c: 666, }, }, }, }); // 方法 function changeInfo() { yk.age = 48; yk.job.a.b.c = 888; // 直接通过数组下标修改,可以触发响应式 yk.hobby[0] = "打豆豆"; } return { yk, changeInfo, }; }, }; </script>
4、计算属性computed
功能和vue2一样,写法稍有不同
<template> 姓:<input v-model="person.firstName"></input> 名: <input v-model="person.lastName"></input> 姓名:<input v-model="person.fullName"></input> </template> <script> //先引入 import {computed,reactive } from 'vue' export default { name: "App", setup() { let person = reactive({ firstName :"小", lastName:"明", fullName:"" }) //计算属性 —— 简写 //let fullName = computed(()=>{ // return person.firstName + '-' + person.lastName //}) //计算属性 —— 完整 person.fullName = computed({ get(){ return person.firstName + '-' + person.lastName }, set(value){ const nameArr = value.split('-') person.firstName = nameArr[0] person.lastName = nameArr[1] } }) return { person }; }, }; </script>
5、v-model
之前:v-model="msg" msg.sync=""
现在:v-model:value="msg"
6、计算属性watch
和计算属性差不多,在vue3中和只是语法上上的改变。
注意:
1、监视ref定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
2、监视reactive定义的响应式数据中某个属性时(这个属性需是对象):deep配置有效
//情况一:监视ref定义的响应式数据 watch(sum,(newValue,oldValue)=>{ console.log('sum变化了',newValue,oldValue) }) //如果用ref定义了一个对象 watch(person.value,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) }) //情况二:监视多个ref定义的响应式数据 watch([sum,msg],(newValue,oldValue)=>{ console.log('sum或msg变化了',newValue,oldValue) }) //情况三:监视reactive定义的响应式数据 watch(person,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) },{immediate:true,deep:false}) //此处的deep配置不再奏效 //情况四:监视reactive定义的响应式数据中的某个属性 watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{immediate:true,deep:true}) //情况五:监视多个reactive定义的响应式数据中的某些属性 watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{immediate:true,deep:true}) //特殊情况 //person.job中的job也是一个对象 watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
7、watchEffect函数
watch是:既要指明监视的属性,也要指明监视的回调。
watchEffect是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
这个函数的功能和计算属性差不多,但是:
但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。 watchEffect(()=>{ const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') })
8、生命周期
1、vue3.0中可以继续使用vue2.x中的生命周期钩子,但是有两个被更名: beforeDestroy改成beforUnmount destroyed改成 unmounted 2、vue3.0也提供了composition API形式的生命周期钩子,与vue2.x钩子对应关系如下: beforeCreate======>setup() created==========>setup() beforeMount======>onBeforeMount mounted=========>onMounted beforeUpdate=====>onBeforeUpdate updated =========>onUpdated beforeUnmount ===>onBeforeUnmount unmounted ======>onUnmounted
9、自定义hook函数
自定义hook的优势:复用代码,让setup中的逻辑更清晰。
book函数point.js:
import { reactive, onMounted, onBeforeUnmount } from "vue"; export default function() { //实现鼠标“打点”相关的数据 let point = reactive({ x: 0, y: 0, }); //实现鼠标“打点”相关的方法 function savePoint(event) { point.x = event.pageX; point.y = event.pageY; console.log(event.pageX, event.pageY); } //实现鼠标“打点”相关的生命周期钩子 onMounted(() => { window.addEventListener("click", savePoint); }); onBeforeUnmount(() => { window.removeEventListener("click", savePoint); }); return point; }
页面中使用:
<template> <h2>当前点击时鼠标的坐标为:x:{{point.x}},y:{{point.y}}</h2> </template> <script> import usePoint from '../hook/point.js' export default { name:'HelloWorld', setup(){ const point = usePoint() return {point} } } </script>
10、toRef和toRefs
语法:const name = toRef(person,‘name’)应用: 要将响应式对象中的某个属性单独提供给外部使用时。
扩展:toRefs与toRef功能一致,但可以批量创建多个 ref 对象,
语法:toRefs(person)
<template> <h4>{{person}}</h4> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> <h2>薪资:{{job.j1.salary}}K</h2> <button @click="name+='~'">修改姓名</button> <button @click="age++">增长年龄</button> <button @click="job.j1.salary++">涨薪</button> </template> <script> import {ref,reactive,toRef,toRefs} from 'vue' export default { name: 'HelloWorld', setup(){ let person = reactive({ name:'张三', age:18, job:{ j1:{ salary:20 } } }) // const name1 = person.name // console.log('%%%',name1) // const name2 = toRef(person,'name') // console.log('####',name2) const x = toRefs(person) console.log('******',x) return { person, // name:toRef(person,'name'), // age:toRef(person,'age'), // salary:toRef(person.job.j1,'salary'), ...toRefs(person) } } } </script>
参考教程连接:https://blog.csdn.net/webtext/article/details/123061587