写给懒人的vue3快17查阅📄17 radawn 2024-02-07 5,036 阅读7分钟 大家好,这是戄1724年第丄17篇文章~祝大家新春快乐🎄17/p> 写了多年react,但是新入职的公司技术栈是vue,部门后续会升级到VUE3。并且发现身边不少小伙伴是react转vue,因项目原因霄17要快速上手,扄17以输出了丄17篇学习笔记,方便快17上手查阅1717/p> Vue 3 相对亄17 Vue 2 有许多改进和新功能,其中丄17些主要的变化包括$17/strong> 使用 Composition API:Vue 3 引入亄17 Composition API,这是一种新的17更灵活的组件编写方式,允许更好地组织和复用代码〄17/li> 改进的17能:Vue 3 在17能方面进行了许多改进,包括更快的渲染17度、更小的捆绑体积和更好的内存管理〄17/li> 更好的17 TypeScript 支持:Vue 3 提供了更好的 TypeScript 支持,包括类型推断和类型注解〄17/li> 新的路由器和状17管理库:Vue 3 引入了新的路由器和状态管理库,称丄17 Vue Router 咄17 Vuex 4〄17/li> 更好的17 tree-shaking 支持:Vue 3 更好地支挄17 tree-shaking,这意味睄17在生产环境中,只打包实际使用的代码,从17减少应用程序的大小〄17/li> setup 圄17 Vue 3 中,setup 是一个新的组件17项,用于定义组件的逻辑和状态1717过使用 setup,可以更清晰地组织组件的逻辑和状态,并使其更易于测试和维护1717code>也可以直接把setup写在script标签上哦〄17/p> <template> <div> {{ count }} </div> </template> <script> export default { name: 'MyComponent', setup() { const count = ref(0); const increment = () => { count.value++; }; return { count, increment }; } }; </script> 响应式数捄17/h3> 使用reactive创建对象类型响应式数据,如果给reactive重新分配丄17个对象,会失去响应式,可以使甄17code>Object.assign()去整体替换17使用ref创建基本类型响应数据 ref也可以创建对象类型的响应数据。若层级较深,建议reactive <script setup> import { reactive , ref } from 'vue'; let obj=reactive({ a:1, b:{ c:3 d:4 } }) let str=ref('hi') const fnc=()=>{ str.value = 'hello!'//记得劄17.value } </script> 解构响应式对豄17/h3> toRefs可用来解构,该对象的每个属17都是独立的 ref 对象,并保持响应弄17/p> import { reactive, toRefs } from 'vue'; let info = reactive({ name: 'Echo', age: 26, gender: 'Male', }) let { name, age, gender } = toRefs(info);//解构数据,并保持响应弄17/span> 如何监听多个数据$17/h3> 监听多个数据,第丄17个参数需用数组包起来;如果监听非对象类型,需写成函数形式,若监听 reactive 定义的对象类型,就默认开启深度监听1717/p> 弄17启immediate :上来就调用监听里的内容,类似react中的useEffect(()=>{},[]) import { watch } from 'vue'; //监听active、type watch([() => props.active, ()=> props.type],(nv, ov) => { // nv代表朄17新数据,ov是17数捄17/span> console.log(nv) //弄17启deep代表深度监听 },{ deep:true, immediate: true }) 解放双手,自动检测变匄17/h3> watchEffect可以自动棄17测到属17的变化,无霄17手动指定要监听的属171717/p> 与传统的 watch 不同,watchEffect 会在属17变化时自动执行副作用函数,并且可以返回丄17个清理函数,用于在组件卸载时清理副作用1717/p> import { watchEffect } from 'vue'; //只要temp.val跟json.val发生变更,就会自动执行watchEffect内的副作用函敄17/span> watchEffect(()=>{ if(temp.val>60||json.val>60){ console.log('发17请汄17') } }) 接收props 父子组件传17,霄17要使甄17code>defineProps接收props,案例如下: <script setup> import { defineProps } from 'vue'; //子组件接收props const props = defineProps({ language: { type: Object, //也可以使用withDefaults设置默认倄17/span> default: () => ({}), }, cookieCountry: { type: String, default: '' } }) </script> Ref属17(父子交互$17/h3> 通过 Ref 属1717/code>,可以从父组件中访问子组件的属17和方法,或者直接操佄17 DOM 元素〄17/p> <template> <div ref="myDiv">Hello, World!</div> </template> <script> import { ref, onMounted } from 'vue'; export default { setup() { const myDiv = ref(null); //mounted是生命周期,代表挂载完毕 onMounted(() => { myDiv.value.style.color = 'red';//将myDiv的颜色改成红艄17/span> }); return { myDiv }; } }; </script> 如果父组件想访问子组件的内容,子组件霄17使用defineExpose将内容导出1717/p> defineExpose将组件中的属性或方法暴露给外部环境,以便在其他组件或模板中使用1717/p> <template> <card-num ref="cardNumRef" /> </template> <script setup> import { ref } from 'vue'; const resetAllRefData = () => { console.log(cardNumRef.value.cardNo)//获取子组件中的cardNo倄17/span> } </script> cardNum组件$17/p> <script setup> import { defineExpose } from 'vue'; const resetData = () => { cardNo.value = '' cardNum.value = '' } //暴露 defineExpose({ resetData }) </script> 自定义事仄17/h3> defineEmits 昄17 Vue 3 中的丄17个新特17,它允许你在组件中自定义事件17在父组件中,可以使甄17 v-on 指令来监听自定义事件〄17/p> <template> <!-- 自定义一个叫update的事仄17 --> <Child @update="onUpdate"/> </template> <script setup> import Child from '/Child.vue' const onUpdate = (value)=>{ console.log(value)//666 } </script> Child组件$17/p> <template> <!-- 点击button,将666传给父,emits 触发事件 --> <button @click="emits('update',666)"/> </template> <script setup> import { defineEmits,onMounted } from 'vue' // 定义 emits const emits = defineEmits(['update'])//接收事件名update </script> vue3 生命周期 <script setup> import { onMounted,onBeforeMount,onUpdated,unmounted } from 'vue'; //挂载剄17/span> onBeforeMount(()=>{}) //挂载完毕 onMounted(()=>{}) //更新完毕 onUpdated(()=>{}) //卸载完毕 onUnmounted(()=>{}) </script> beforeCreate: 在实例初始化之后〄17/p> created: 在实例创建完成后被立即调用1717/p> beforeUpdate: 数据更新时1717/p> beforeUnmount: 实例锄17毁之前1717/p> 以此类推... 作用域插槄17/h3> 作用域插槽,它允许你在一个组件中定义具有屄17部作用域的插槽1717过作用域插槽,可以将组件的属17传递给插槽内容,从而使插槽内容能够根据组件的状态进行动态渲染1717br> 作用域插槽使甄17 v-slot 指令来定义,它可以接受一个参数,该参数指定了要传递给插槽的属性名〄17br> 下面是具名插槄17+作用域插槽的例子$17/p> 如果不写名字就是默认插槽 <!-- <template #ScopedSlot="{list}"></template> --> <template> <SlotComponent> <!-- ScopedSlot是插槽名,params子组件传的是参数 --> <template v-slot:ScopedSlot='params'> <ul> <li v-for='d in params.list' :key="d.id"> {{d.name}} </li> </ul> </template> </SlotComponent> </template> <script> import SlotComponent from './SlotComponent.vue'; export default { components: { SlotComponent, }, }; </script> 子组件SlotComponent$17/p> <template> <div> <slot name="ScopedSlot" :list="list" /> </div> </template> <script setup> import {reactive} from 'vue' let list=reactive([ {id:'001',name:'test-01'}, {id:'002',name:'test-02'} ]) </script> 提高性能-浅层次响庄17/h3> shallowRef()丄17code>ref()类似,但它不支持深度响应性,是浅层次响应〄17/p> 对嵌套对象的属17或数组元素的修改不会触发响应1717这在需要优化17能并避免不必要的深度响应17跟踪时非常有用。这样使用浅的响应式提高性能,只有最外一层是响应式1717/p> shallowReactive同理 响应式对豄17-》原始对豄17/h3> toRaw() 是用于将响应式对象转换为原始对象。以便在霄17要时进行操作。转换后的对象不再具有响应17,对其进行的更改不会触叄17 Vue 的更新机制1717/p> import { reactive, toRaw } from 'vue'; const obj = reactive({ name: 'John', age: 24 }); const rawObj = toRaw(obj); console.log(rawObj); // 输出:{ name: 'John', age: 24 } rawObj.name = 'Alice'; console.log(obj.name); // 输出$17'John' 创建自定义的ref customRef 昄17 Vue 3 中引入的丄17个新特17,用于创建自定义的ref,让用户来决定什么时候收集和执行依赖,从而更好地控制行为和17辑。customRef 接受 track 咄17 trigger 两个函数作为参数,并返回丄17个带朄17 get 咄17 set 方法的对象1717/p> track用于追踪数据,trigger 用于触发响应,更新视图17一舄17 track 方法放在 get 中,trigger 方法放在 set 中1717/p> import { customRef } from 'vue'; const myCustomRef = customRef((track, trigger) => { // 在这里编写自定义的17辑 return{ get(){ track()//跟踪 }, set(value){ trigger()//触发 } } }); // 在组件中使用自定义的 ref const myComponent = { template: `<div ref="myCustomRef"></div>`, setup() { const myCustomRef = myCustomRef(); console.log(myCustomRef.value); // 获取当前的引用1717/span> } }; 获取未在 props 中声明的属1717/h3> $attrs 可以用于获取父组件传递的属1717,或17在组件内部未在 props 中声明的属171717/p> 注意$17$attrs 中的属17是只读的,不能直接修改。如果需要在组件内部处理未在 props 中声明的属17,可以使用 v-bind 指令或动态组件来实现〄17/p> <!-- 传17给子组仄17 --> <child-component :id="id" :style="style" some-other-attribute="value"></child-component> export default { props: ['id', 'style'],//props只接收了id跟style created() { console.log(this.$attrs); //$attrs能实现全部获叄17/span> // 输出:{ id: "id", style: "style", someOtherAttribute: "value" } } }; 组件间17信 $parent和refs 是用于组件间通信和访问的属1717需要配各17code>defineExpose丄17起使甄17/p> refs 可以用于在模板中访问子组件或 DOM 元素。在模板中的元素或组件上使用 ref 属17来定义丄17个引用名称,然后在组件的 JavaScript 代码中17过 $refs 访问到这个元素或组件〄17/li> parent 指向当前组件的父组件实例。17过 $parent,可以访问父组件的属性17方法和事件等1717/li> 父组仄17 $refs示例代码$17/p> <template> <div> <button @click="myButton($refs)">点击戄17span class="hljs-tag"></button> <!-- 子组仄17 --> <ChildComponent1 /> <ChildComponent2 /> </div> </template> <script setup> import ChildComponent1 from '/ChildComponent1.vue' import ChildComponent2 from '/ChildComponent2.vue' import { ref,defineExpose } from 'vue'; let value=ref('666') function myButton(refs){ // refs是子组件的集各17/span> for(let key in refs){ refs[key].val=+1//操作每个子组件的val+1 } } defineExpose({value}) </script> 子组仄17 $parent示例代码$17/p> <template> <div> <button @click="parentMethod($parent)">点击戄17span class="hljs-tag"></button> </div> </template> <script> import { ref } from 'vue'; let value=ref('888') function myButton(parent){ parent.value-=1//子操作父的value } defineExpose({value}) </script> 隔代通信 provide 是一个用于提供依赖注入的选项。可用于隔代通信;它允许父组件向其后代组件提供共享的数据或功能17在子组件中可以通过 inject 选项来接收父组件提供的属性1717/p> <template> <div> <Child /> </div> </template> <script setup> import Child from './Child.vue'; import { ref,provide } from 'vue'; let value=ref({ name:'sam', age:18 }) //provide向后代提供数捄17/span> provide('val',value) </script> 子组件Child$17/p> <template> <div> <!-- sam --> 姓名:{{data.name}} <!-- 18 --> 年龄:{{data.age}} </div> </template> <script setup> import { inject } from 'vue'; //inject接收数据 let data=inject('val',{//第二个参数是默认倄17/span> name:'未知', age:0 }) </script> 有bug?想补充$17/h3> 更多参17官网:v3-migration.vuejs.org/zh/ 感谢大家观看这篇文章,有任何问题或想和我交流,请直接留言$17/p> 发现文章有不妥之处,也可指出交流,感谢阅读~