irpas技术客

助你上手Vue3全家桶之Vue3教程_pdd11997110103

网络 8342

目录 前言1,setup1.1,返回值1.2,注意点1.3,语法1.4,setup的参数 2,ref 创建响应式数据3,reactive 创建响应式数据4,computed 计算属性5,watch 监听6,watchEffect 监听回调7,生命周期7.1,改变7.2,语法 8,toRef 创建ref9,toRefs 响应式转换10,shallowReactive 响应式外层转换11,shallowRef 基本数据响应式12,readonly 响应式变只读13,shallowReadonly 响应式变只读14,toRaw 响应式变非响应式15,markRaw 标记永远不响应式16,customRef 依赖更新控制17,provide & inject 通信18,响应式数据的判断18.1,isRef18.2,isReactive18.3,isReadonly18.4,isProxy 19,teleport 移动dom组件20,Suspense 异步渲染组件21,全局API调整22,移除api23,Ref 获取DOM23.1,单个ref23.2,循环中的ref 24,emits 自定义事件25,$nextTick 异步更新26,hook 生命周期事件

前言

这些内容是博主在学习过程中记录下来的,有一些不重要的点就跳过了,需要时自行查询文档。其实V2到V3的学习成本不高,熟悉V2的话,看完这篇文章就可以上手V3。

Vue3官网

在线源码编译地址

1,setup

setup是所有Composition API的容器,值为一个函数。组件中所用到的数据、方法等等,均要配置在setup中,它会在beforeCreate之前执行一次,注意:V3里this不再是指向Vue实例,访问this会是undefined

1.1,返回值
若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。若返回一个渲染函数:则可以自定义渲染内容。 1.2,注意点

尽量不要与V2配置混用

V2配置(data、methos、computed…)中可以访问到setup中的属性、方法。 但在setup中不能访问到V2配置(data、methods、computed…)。 如果有重名, setup优先。

setup不能是一个async函数

因为返回值不再return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

1.3,语法
<script> import { ref, reactive } from 'vue' export default { name: 'Home', setup(props, context) { const title = ref('标题') const data = reactive({ value: '哈哈哈' }) return { title, data } } } </script> 1.4,setup的参数

props:值为对象,包含组件外部传递过来,且组件内部声明接收了的属性

context:上下文对象

attrs: 值为对象,包含组件外部传递过来,但没有在props配置中声明的属性, 相当于this.$attrsslots: 收到的插槽内容, 相当于this.$slotsemit: 分发自定义事件的函数, 相当于this.$emit 2,ref 创建响应式数据

使用ref可以创建一个包含响应式数据的引用对象(reference对象,简称ref对象),可以是基本类型、也可以是对象。

语法

// 创建 const xxx = ref(value) // 使用 xxx.value // 在模板中 <div>{{xxx}}</div> 3,reactive 创建响应式数据

定义一个对象类型的响应式数据,内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作

语法

// 创建 const xxx = reactive({ xxx: '' }) // 使用 xxx.xxx 4,computed 计算属性

与V2中computed配置功能一致

语法

import { computed } from 'vue' setup(){ // 简写语法 let fullName = computed(() => { return person.firstName + '-' + person.lastName }) // 完整语法 let fullName = computed({ get(){ return person.firstName + '-' + person.lastName }, set(value){ const nameArr = value.split('-') person.firstName = nameArr[0] person.lastName = nameArr[1] } }) return fullName } 5,watch 监听

与V2中watch配置功能一致,语法有点改动

语法

情况一:监视ref定义的响应式数据 watch(sum, (newValue, oldValue) => { console.log('sum变化了', newValue, oldValue) }, {immediate:true}) 情况二:监视多个ref定义的响应式数据 watch([sum, msg], (newValue,oldValue) => { console.log('sum或msg变化了', newValue,oldValue) }) 情况三:监视reactive定义的响应式数据 // 若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue // 若watch监视的是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 }) 特殊情况:此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效 watch(() => person.job, (newValue, oldValue) => { console.log('person的job变化了', newValue, oldValue) }, { deep:true }) 6,watchEffect 监听回调

和watch的区别是,watch既要指明监视的属性,也要指明监视的回调。而watchEffect,不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性,不用写返回值。

语法

// 回调中用到的数据只要发生变化,则直接重新执行回调 watchEffect(() => { const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') }) 7,生命周期

生命周期全都写在setup中

7.1,改变
beforeDestroy 改名为 beforeUnmountdestroyed 改名为 unmountedbeforeCreate => setupcreated => setupbeforeMount => onBeforeMountmounted => onMountedbeforeUpdate => onBeforeUpdateupdated => onUpdatedbeforeUnmount => onBeforeUnmountunmounted => onUnmounted 7.2,语法
setup() { onMounted(() => { console.log('mounted') }) } 8,toRef 创建ref

创建一个ref对象,其value值指向另一个对象中的某个属性

语法

const state = reactive({ foo: 1, bar: 2 }) const fooRef = toRef(state, 'foo') // 传递props export default { setup(props) { useSomeFeature(toRef(props, 'foo')) } } 9,toRefs 响应式转换

将响应式对象转换为普通对象,其中结果对象的每个property都是指向原始对象相应property的ref

语法

const state = reactive({ foo: 1, bar: 2 }) const stateAsRefs = toRefs(state) // 此时state和stateAsRefs是关联的 10,shallowReactive 响应式外层转换

只处理对象最外层属性的响应式(浅响应式)。适用于:一个对象数据,结构比较深, 但变化时只是外层属性变化

语法

const state = shallowReactive({ foo: 1, nested: { bar: 2 } }) 11,shallowRef 基本数据响应式

只处理基本数据类型的响应式, 不进行对象的响应式处理。适用于:一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换

语法

const shallow = shallowRef({ greet: 'Hello, world' }) 12,readonly 响应式变只读

让一个响应式数据变为只读的(深只读),应用于不希望数据被修改时

语法

const shallow = shallowRef({ greet: 'Hello, world', // 只读 nested: { bar: 2 // 只读 } }) 13,shallowReadonly 响应式变只读

让一个响应式数据变为只读的(浅只读),应用于不希望数据被修改时

语法

const shallow = shallowReadonly({ foo: 1, // 只读 nested: { bar: 2 // 非只读 } }) 14,toRaw 响应式变非响应式

将一个由reactive生成的响应式对象转为普通对象,对这个普通对象的所有操作,不会引起页面更新。

语法

const foo = {} const Foo = reactive(foo) console.log(toRaw(Foo) === foo) // true 15,markRaw 标记永远不响应式

标记一个对象,使其永远不会再成为响应式对象,有些值不应被设置为响应式的,例如复杂的第三方类库等,当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

语法

const foo = markRaw({}) console.log(isReactive(reactive(foo))) // false // 嵌套在其他响应式对象中时也可以使用 const bar = reactive({ foo }) console.log(isReactive(bar.foo)) // false 16,customRef 依赖更新控制

创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收track和trigger函数作为参数,并且应该返回一个带有get和set的对象。

语法

<script> import { customRef } from 'vue' export default { name: 'Home', setup() { // 实现防抖函数 const fn = function(value, delay = 500) { let timeout return customRef((track, trigger) => { return { get() { track() return value }, set(newValue) { clearInterval(timeout) timeout = setTimeout(() => { console.log(newValue) value = newValue trigger() }, delay) } } }) } const keyword = fn('', 500) return { keyword } } } </script> 17,provide & inject 通信

实现祖与后代组件间通信,父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据

语法

// 祖组件 setup(){ let car = reactive({ name:'奔驰', price:'40万' }) provide('car', car) } // 后代组件 setup(props, context){ const car = inject('car') return { car } } 18,响应式数据的判断
18.1,isRef

检查一个值是否为一个ref对象

语法

const val = ref('xxx') isRef(val) // true 18.2,isReactive

检查一个值是否为一个isReactive对象

语法

const val = isReactive({}) isRef(val) // true 18.3,isReadonly

检查一个对象是否是由readonly创建的只读代理

语法

const state = reactive({ name: 'John' }) console.log(isReactive(state)) // true 18.4,isProxy

检查对象是否是由reactive或readonly创建的proxy

语法

const state = reactive({ name: 'John' }) console.log(isProxy(state)) // true 19,teleport 移动dom组件

Teleport提供了一种干净的方法,允许我们控制在DOM中哪个父节点下渲染了HTML,而不必求助于全局状态或将其拆分为两个组件。

语法

<teleport to="移动位置"> <div v-if="isShow" class="mask"> <div class="dialog"> <h3>我是一个弹窗</h3> <button @click="isShow = false">关闭弹窗</button> </div> </div> </teleport> // to的格式 <teleport to="#some-id" /> <teleport to=".some-class" /> <teleport to="[data-teleport]" /> // disabled的格式 <teleport to="#popup" :disabled="displayVideoInline"> <video src="./my-movie.mp4"> </teleport> 20,Suspense 异步渲染组件

等待异步组件时先渲染一些额外内容,让应用有更好的用户体验

语法

<template> <div class="app"> <h3>我是App组件</h3> <Suspense> <template #default> <Child/> </template> <template #fallback> <h3>加载中.....</h3> </template> </Suspense> </div> </template> import { defineAsyncComponent } from 'vue' const Child = defineAsyncComponent(() => import('./components/Child.vue')) components: { Child } 21,全局API调整

将全局的API,即:Vue.xxx调整到应用实例(app)上

V2的apiV3的apiVue.config.xxxxapp.config.xxxxVue.componentapp.componentVue.directiveapp.directiveVue.mixinapp.mixinVue.useapp.useVue.prototypeapp.config.globalProperties
22,移除api
名称现状Vue.config.productionTip已移除config.keyCodes已移除$children已移除$listeners已移除$on已移除$off已移除$once已移除filters已移除.native已移除
23,Ref 获取DOM

由于V3中不在存在this,所以ref的获取调整了

23.1,单个ref

语法

<div ref="Qrcode" class="qr_codeode_url" /> import { ref } from 'vue' export default { setup() { const Qrcode = ref(null) // 挂载后 onMounted(() => { console.log(Qrcode.value) }) return { Qrcode } } } 23.2,循环中的ref

V3中在for循环元素上绑定ref将不再自动创建$ref数组。要从单个绑定获取多个ref,请将ref绑定到一个更灵活的函数上

语法

<div v-for="item in list" :ref="setItemRef"></div> import { onBeforeUpdate, onUpdated } from 'vue' export default { setup() { let itemRefs = [] const setItemRef = el => { if (el) { itemRefs.push(el) } } onBeforeUpdate(() => { itemRefs = [] }) onUpdated(() => { console.log(itemRefs) }) return { setItemRef } } } itemRefs不必是数组:它也可以是一个对象,其ref可以通过迭代的key被设置如有需要,itemRef也可以是响应式的,且可以被侦听 24,emits 自定义事件

定义一个组件可以向其父组件触发的事件

// 在子组件中 <h1 @click="father">{{ msg }}</h1> export default { name: 'HelloWorld', props: { msg: { type: String, default: '' } }, emits: ['close'], setup(props, { emit }) { const father = function() { emit('close', 'child') } return { father } } } // 在父组件中 <HelloWorld :msg="msg" @click="fn" @close="fn2" /> 25,$nextTick 异步更新

使用方式修改

import { nextTick } from 'vue' nextTick(() => { // ... }) 26,hook 生命周期事件

通过事件来监听组件生命周期中的关键阶段

语法

// V2的语法 <template> <child-component @hook:updated="onUpdated"> </template> // V3的语法 <template> <child-component @vnode-updated="onUpdated"> </template> // 驼峰写法 <template> <child-component @vnodeUpdated="onUpdated"> </template

如果看了觉得有帮助的,我是@鹏多多i,欢迎 点赞 关注 评论;END

PS:在本页按F12,在console中输入document.querySelectorAll('.tool-item-href')[0].click(),有惊喜哦~

公众号

往期文章

助你上手Vue3全家桶之Vue-Router4教程助你上手Vue3全家桶之VueX4教程超详细!Vue的九种通信方式超详细!Vuex手把手教程超详细!Vue-Router手把手教程使用nvm管理node.js版本以及更换npm淘宝镜像源vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令

个人主页

CSDNGitHub简书博客园掘金


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #计算属性5watch #监听6watchEffect #创建ref9toRefs