vue3总结
1.setup
setup是vue3api的大舞台,vue3所有新增的api都要在里面写具体如下
::注意点
1.setup函数的执行顺序在created和beforecreate前面
2.setup函数只能是同步不能是async修饰的异步,因为返回值不能时return的对象而是promise,模板看不到return对象的属性。(若用了Suspense和异步组件配合,可以异步)
3.setup由于执行在created和beforecreate前面所以无法使用 data 和 methods 的变量和方法,this为undefined
4.setup能接受到两个参数props和context
1.props,是一个对象,该对象包含的属性是组件外部传递过来的,且组件内部声明接收的属性。
context和他的三个值(要接收)
1.attrs:当父组件给子组件传参时,如果props没接收,就会在这里捡漏。
2.slots:接受插槽内容
3.emit:(自定义函数)
<template> <div> {{person.name}} </div> </template> <script> import { reactive } from "vue"; export default { name: "test", //接受 props:['msg','hook'], emits:['good'], slots:['qwe'], setup() { let person = reactive({ name: "小明", age: 18, }); return { person, }; }, }; </script>
2.ref和reactive的用法和区别(要引入)
使用时要引入import { ref,reactive } from "vue";
let age = ref(20);
let data= reactive({name:'小明'})
ref和reactive都是用于让数据变成响应式的,区别在于ref依旧对普通数据采用的是Object.defineProperty,对对象会在里面调用一个Proxy
reactive仅仅使用的是proxy也就是(refImpl),原型是用Reflect内射的
3.computed (要引入)
在2里叫计算属性这里叫计算函数
let fullName = computed({ get() { return data.firstName + "-----" + data.lastName; }, set(value) { console.log(value, 56); var p = value.split("-----"); console.log(p, 65); data.firstName = p[0]; data.lastName = p[1]; }, }); let fullName=computed(()=>{ return data.firstName+'-----'+data.lastName })
4.watch监听(要引入)
// 监听单个 watch( sum,(newdata, olddata) => { console.log(newdata, olddata, "监听单个ref数据"); }, { immediate: true } ); // 监听深层对象 watch(() => data.a.b.c, (newdata, olddata) => { console.log(newdata, olddata, "监听对象reactive数据"); } ); //监听多个属性 watch([() => data.a.b.c, () => data.num], (newdata, olddata) => { console.log(newdata, olddata, "监听多个对象reactive数据"); });
5.watchEffect(要引入)
监听所有,没有具体的监听属性,在里面写谁就监听谁,默认监听一次
watchEffect(() => { const x1 = data.num; console.log(x1, 5); console.log("watchEffect触发了"); });
6.生命周期(要引入)
可在setup外面写,与2的不同在于
beforeDestroy
->beforeUnmount
destroyed
->unmounted
setup里写就是
beforeCreate -> 使用 setup() created -> 使用 setup() beforeMount -> onBeforeMount mounted -> onMounted beforeUpdate -> onBeforeUpdate updated -> onUpdated beforeDestroy -> onBeforeUnmount destroyed -> onUnmounted
7.hook(封装api)
hook文件夹/usrpoint import {onMounted,reactive,onUnmounted}from 'vue' export default function (){ const point=reactive({ x:0, y:0 }) function page(){ point.x=event.pageX point.y=event.pageY } onMounted(()=>{ window.addEventListener('click',page) }) onUnmounted(()=>{ window.removeEventListener('click',page) }) return point } //在用到的组件里 //import hook from './hooks/usrPoint' //let point=hook()8.toRef和toRefs(要引入)
toRef
<template> <div> <hr /> {{ person }} <br /> {{ name }} <br /> {{ age }} <br /> <button @click="name += '~'">点击加</button> <button @click="age++">点击加</button> </div> </template> <script> import { reactive, toRef} from "vue"; export default { name: "test", setup() { let person = reactive({ name: "小明", age: 18, job: { a1: { c: 1, }, }, }); return { person, age: toRef(person, "age"), name: toRef(person, "name"), }; }, }; </script>toRefs
<template> <div> <hr /> {{ name }} <br /> {{ age }}<br /> {{job.a1.c}} <br /> <button @click="name += '~'">点击加</button> <button @click="age++">点击加</button> <button @click="job.a1.c++">点击加</button> </div> </template> <script> import { reactive, toRefs} from "vue"; export default { name: "test", setup() { let person = reactive({ name: "小明", age: 18, job: { a1: { c: 1, }, }, }); return { ...toRefs(person) }; }, }; </script>当你使用ref或者reactive时,生成的数据到页面不美观,这个时候借助toRef中的get函数反射到你指定的对象里进行修改。
toRef和toRefs的区别是一个只对单个数据进行反射,一个能深入对象里动态反射多个属性
9.shallowRef和shallowReactive(要引入)
1.shallowReactive 只对浅层对象的属性发生作用,如下,我这个对象person的name,age才有数据劫持。
<template> <div> <hr /> {{ name }} <br /> {{ age }}<br /> {{job.a1.c}} <br /> <button @click="name += '~'">点击加</button> <button @click="age++">点击加</button> <button @click="job.a1.c++">点击加</button> </div> </template> <script> import { reactive, toRefs,shallowRef,shallowReactive} from "vue"; export default { name: "test", setup() { let person = shallowReactive({ name: "小明", age: 18, job: { a1: { c: 1, }, }, }); return { ...toRefs(person) }; }, }; </script>2.shallowRef(只对基本数据类型有用)
和ref的区别是 ref可以监听引用数据类型
10.readonly和shallowReadonly(要引入)
readonly让一个响应的数据变成只读的(深只读)
shallowReadonly 让一个响应数据(对象)变成(浅只读)
如图shallowReadonly 只对person.job发生变化
<template> <div> <hr /> {{ name }} <br /> {{ age }}<br /> {{job.a1.c}} <br /> <button @click="obj += '~'">点击加</button> <button @click="name += '~'">点击加</button> <button @click="age++">点击加</button> <button @click="job.a1.c++">点击加</button> </div> </template> <script> import { reactive, toRefs,shallowReadonly} from "vue"; export default { name: "test", setup() { let person = reactive({ name: "小明", age: 18, job: { a1: { c: 1, }, }, }); person=shallowReadonly(person) return { ...toRefs(person), }; }, }; </script>11.toRaw和markRaw(要引入)
toRaw,将一个reactive生成的响应式改为普通的对象
<template> <div> <hr /> {{ name }} <br /> {{ age }}<br /> {{job.a1.c}} <br /> <button @click="obj += '~'">点击加</button> <button @click="name += '~'">点击加</button> <button @click="age++">点击加</button> <button @click="job.a1.c++">点击加</button> <button @click="original">回到原始数据</button> </div> </template> <script> import { reactive, toRefs,toRaw} from "vue"; export default { name: "test", setup() { let person = reactive({ name: "小明", age: 18, job: { a1: { c: 1, }, }, }); function original(){ person=toRaw(person) //只读 person.age++ console.log(person); } return { original, ...toRefs(person), }; }, }; </script>markRaw:标记一个对象,使她永远不成为响应式对象
12.customRef(要引入)
自定义ref
<template> <div> <hr /> <input type="text" v-model="keyow" /> <br /> {{ keyow }} </div> </template> <script> import { customRef } from "vue"; export default { name: "test", setup() { let time let keyow = myRef(""); function myRef(value) { return customRef((track,trigger) => { return { get() { track() //通知vue追踪数据变化 return value; }, set(newdata){ value=newdata clearTimeout(time) time= setTimeout(()=>{ trigger() //通知模板从新解析 },3000) } }; }); } return { keyow, myRef, }; }, }; </script>13.provide和inject(要引入)
用于爷爷组件给后代传值
用法:
爷爷组件
<template> <div> parent {{ name }}---{{ price }} <div> <child /> </div> </div> </template> <script> import { reactive, toRefs, provide } from "vue"; import child from "./child.vue"; export default { name:'parent', components: { child, }, setup() { let car = reactive({ name: "保时捷", price: "90w", }); provide("car", car); return { ...toRefs(car), }; }, }; </script>
儿子组件
<template> <div> child <div> <son /> </div> </div> </template> <script> import son from './son.vue' export default { name:'child', components:{ son }, setup(){ } } </script>
孙子组件
<template> <div> son---{{name}}---{{price}} </div> </template> <script> import {inject,toRefs} from 'vue' export default { name:'son', setup(){ let car=inject('car') return { ...toRefs(car) } } } </script>
爷爷组件使用provide,后代用inject接收
注意:该方法虽然可以用于父传子但不建议使用
14.isRef,isReactive,isProxy,isReadonly(判断属性类型创建的)
<template> <div> parent <div> <child /> </div> </div> </template> <script> import { reactive, ref,readonly,isRef,isReactive,isProxy,isReadonly } from "vue"; import child from "./child.vue"; export default { name:'parent', components: { child, }, setup() { let num=ref(0) let car = reactive({ name: "保时捷", price: "90w", }); let bba=readonly(car) console.log(isRef(nreactivem)); console.log(isReactive(car)); console.log(isReadonly(bba)); console.log(isProxy(bba)); return { }; }, }; </script>
15.Fragment组件
vue2时需要用一个根标签包住剩下的标签,在但这让每个组件都有个根标签,vue3在这边做了处理,组件内部不需要根标签,而是自动生成一个Fragment组件标签
16.teleport
当你在子组件或者孙子组件中写遮罩这种全局样式,会导致父组件和爷爷组件默认被撑大,
使用teleport 的to属性会将这段遮罩代码默认加到你想放到的地方,我这里就是body
<template> <div> son---{{ name }}---{{ price }} <button @click="isdiogin=true">点击出现弹框</button> <teleport to='body'> <div v-if="isdiogin" class="box"> <ul> <li>1</li> <li>1</li> <li>1</li> </ul> <button @click="isdiogin=false">关闭</button> </div> </teleport> </div> </template> <script> import { inject, toRefs ,ref} from "vue"; export default { name: "son", setup() { let car = inject("car"); let isdiogin=ref(false) return { isdiogin, ...toRefs(car), }; }, }; </script> <style scoped> .box { width: 300px; height: 400px; background: pink; } </style>
17.异步引入组件(Suspense)
<template> <div class="parent"> parent <div> <Suspense> <template v-slot:default> <child /> </template> <template v-slot:fallback> <h3>等待中....</h3> </template> </Suspense> </div> </div> </template> <script> // import child from "./child.vue"; //静态引入 import {defineAsyncComponent} from 'vue' const child =defineAsyncComponent(()=>import('./child')) //异步引入 export default { name:'parent', components: { child, }, setup() { return { }; }, }; </script> <style scoped> .parent { width: 300px; height: 400px; background: rebeccapurple; } </style>
异步引入后自动生成一个api(Suspense),它里面默认有两个插槽,一个是v-slot:default,要展示的,一个是当v-slot:default因某种原因照成显示慢时,就展示v-slot:fallback里的内容。
::注意同时还有控制子组件延迟的方法,当父组件使用Suspense时子组件可以异步
<template> <div class="child"> child...{{num}} <div> <son /> </div> </div> </template> <script> import {ref} from 'vue' import son from './son.vue' export default { name:'child', components:{ son }, async setup(){ let num=ref(3) let p= new Promise((resolve,reject)=>{ setTimeout(() => { resolve(num) }, 3000); }) return await p } } </script> <style scoped> .child { width: 300px; height: 400px; background: yellow; } </style>
18.Vue3(API转移)
之前给子组件绑定@click时间要加native否则会被认为是自定义,现在子组件emits不接收就行了
VUE3(api更新)
于 2022-05-13 18:05:48 首次发布