1、是vue3.0的中的一个新增配置项,值为一个函数。
2、setup是所有composition API(组合式api)展示的舞台。
3、setup函数的两种返回值:
若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
若返回一个渲染函数:则可以自定义渲染内容。(了解) (不常用)
注意点:
1、尽量不要和vue2.x版本混用。
2、setup不能是一个async函数,因为返回值不再是对象, 而是promise, 模板看不到return对象中的属性。
3、setup执行顺序在beforeCreat,并且在setup中this为undefined
4、setUp(props, contex)接受两个参数
<template> <h2>姓名:{{name}}</h2> <h2>年龄:{{age}}</h2> <button @click="sayInfo">显示信息</button> </template> <script> export default { name: "App", setup(){ //此时的数据不具有双向绑定的功能 let name = "小明" let age = 18 // 方法 function sayInfo(){ alert(`你好${name},你太厉害了吧`) } // 想要在模板中使用setup中的方法或者数据,必须return return { name,age, gender,sayInfo } // return ()=> h('h1','试试') } }; </script>
作用:定义一个响应式数据。
语法:let xxx = ref(xxx)
注意点:
<template> <h2>姓名:{{ name }}</h2> <h2>年龄:{{ age }}</h2> <button @click="changeInfo">修改信息</button> </template> <script> import { ref } from "vue"; export default { name: "App", setup() { // 数据 let name = ref("小明"); let age = ref(18); // 方法 function changeInfo() { name.value = "小明"; age.value = 48; } return { name, age, changeInfo, }; }, }; </script>
作用:定义一个响应式对象。
语法:let xxx = reactive(xxx)
注意点:
<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>
与vue2.x相比,功能几乎一样,但是写法有些许变动。
<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>
和计算属性差不多,在vue3中和只是语法上上的改变。
注意点:
//情况一:监视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配置有效
watch是:既要指明监视的属性,也要指明监视的回调。
watchEffect是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
这个函数的功能和计算属性差不多,但是
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。 watchEffect(()=>{ const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') })
1、vue3.0中可以继续使用vue2.x中的生命周期钩子,但是有两个被更名:
2、vue3.0也提供了composition API形式的生命周期钩子,与vue2.x钩子对应关系如下:
创建一个hook文件夹,里面创建文件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>
<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>
toRaw
作用:将一个由reactive生成的响应式对象转为普通对象。
使用场景:
markRaw
作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:
作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
实现防抖效果
<template> <input type="text" v-model="keyWord" /> <h3>{{ keyWord }}</h3> </template> <script> import { customRef } from "vue"; export default { name: "App", setup() { //自定义一个ref——名为:myRef function myRef(value, delay) { let timer; return customRef((track, trigger) => { return { get() { console.log(`有人从myRef这个容器中读取数据了,我把${value}给他了`); track(); // 通知Vue追踪value的变化(提前和get商量一下,让他认为这个value是有用的) return value; }, set(newValue) { console.log(`有人把myRef这个容器中数据改为了:${newValue}`); clearTimeout(timer); timer = setTimeout(() => { value = newValue; trigger(); // 通知Vue去重新解析模板 }, delay); }, }; }); } // let keyWord = ref('hello') //使用Vue提供的ref let keyWord = myRef("hello", 500); //使用程序员自定义的ref return { keyWord }; }, }; </script>
作用:实现祖与后代组件间通信
套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据
具体写法
祖组件中:
setup(){ ...... let car = reactive({name:'奔驰',price:'40万'}) provide('car',car) // 给自己的后代组件传递数据 ...... }
后代组件中:
setup(props,context){ ...... const car = inject('car') // 拿到祖先的数据 return {car} ...... }
isRef: 检查一个值是否为一个 ref 对象。
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理。
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理。
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理。
在Vue2中: 组件必须有一个根标签
在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
好处: 减少标签层级, 减小内存占用
Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。
等待异步组件时渲染一些额外内容,让应用有更好的用户体验
使用步骤:
异步引入组件
import {defineAsyncComponent} from 'vue' const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
使用Suspense包裹组件,并配置好default与 fallback
<template> <div class="app"> <h3>我是App组件</h3> <Suspense> //default:就是组件要显示的内容 <template v-slot:default> <Child/> </template> //fallback:就是组件没加载完全的“备胎” <template v-slot:fallback> <h3>加载中.....</h3> </template> </Suspense> </div> </template>
//Vue2.x写法 .v-enter, .v-leave-to { opacity: 0; } .v-leave, .v-enter-to { opacity: 1; } //Vue3.x写法 .v-enter-from, .v-leave-to { opacity: 0; } .v-leave-from, .v-enter-to { opacity: 1; }
哔哩哔哩的尚硅谷教学视频-笔记
链接:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=158