赞
踩
Vue3.0的设计目标可以概括为体积更小、速度更快、加强TypeScript支持、加强API设计一致性、提高自身可维护性、开放更多底层功能。
<script lang="ts"> import { defineComponent} from 'vue'
export default defineComponent({name: 'App',setup() {return {// 这里的属性 和 方法 会合并到 data 函数 和 methods 对象里}},
}) </script>
script
使用 ts
语言,只需 设置 lang
即可defineComponent
方法创建一个组件export default
直接导出一个组件template
中不再需要一个根元素包裹<template><img alt="Vue logo" src="./assets/logo.png" /><HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</template>
实际上内部会将多个标签包含在一个Fragment
虚拟元素中
好处:减少标签层级, 减小内存占用
在 Vue2
中,我们实现一个功能得分到不同的地方,把数据放在 data
,computed
方法放在 methods
里面,分开的太散乱了,几个功能还好,几十个上百个,那就有点…
所以 Vue3
提出了 Composition API ,它可以把 一个逻辑的代码都收集在一起
单独写个hook
,然后再引入,这样就不到处分布,显得很乱了
setup 是 Composition API 的入口
它在beforeCreate
之前执行一次,beforeCreate
这个钩子 的任务就是初始化,在它之前执行,那么 this
就没有被初始化 this = undefined
这样就不能通过 this
来调用方法 和 获取属性
setup
返回的是一个对象,这个对象的属性会与组件中 data
函数返回的对象进行合并,返回的方法和 methods
合并,合并之后直接可以在模板中使用,如果有重名的情况,会使用 setup
返回的属性和方法,methods
和 data
能够拿到 setup
中的方法应该进行了合并,反之 setup
不能拿到它们的属性和方法,因为这个时候 this
= undefined
setup
使用async
/await
我们需要 setup
返回数据那么它肯定就不能使用 async
修饰,这样返回 promise
是我们不想看见情况,如果我们硬要用 async
修饰,我们就得用的在它的父组件外层需要嵌套一个suspense
(不确定)内置组件,里面放置一些不确定的操作,比如我们就可以把异步组件放入进去
子组件
<template>{{ res }}
</template>
<script lang="ts"> import { defineComponent } from 'vue'
export default defineComponent({name: 'Son',async setup() {const res = await axios.get('地址')return {res,}},
}) </script>
父组件
<template><Suspense><!-- 子组件--><Son></Son></Suspense>
</template>
setup
(props
,context
)
setup
函数中的第一个参数是 props
。它接收父组件传递的值,是的就是父子组件信息传递的 props
第二个参数是 context
里面包含3个属性 { attrs, slots, emit }
,这三个属性大家看名字就应该知道是什么吧 分别对应 this.$attrs
,this.$slots
,this.$emit
attrs
: 除了 props
中的其他属性slots
: 父组件传入插槽内容的对象emit
: 和用于父子组件通信在上面 setup
写的数据都不是响应式的(修改了数据,视图并不会更新)。在 Vue3
中提供了两种方式定义响应式数据:
import { defineComponent, ref } from 'vue'
setup() {// 方式一let number1 = ref(10)// 方式二let num = 0let number2 = ref(num)return {}
},
来查看一下 number1
是什么吧
可以看见的是 number1
是一个 Ref
对象,我们设置的 10
这个值在这个对象的 value
属性上,也就是说我们修改的时候必须要修改的是 number1.value
但是在模板上使用的时候 不用写 number1.value
直接写 number1
即可,在模板编译的时候回自动加上 value
vue 3.0 通过给value
属性添加 getter
/setter
来实现对数据的劫持
<template>{{ number1 }}<button @click="updateNum">+</button>
</template>
<script lang="ts"> import { defineComponent, ref } from 'vue'
export default defineComponent({name: 'Son',setup() {let number1 = ref(10)// 修改 number1function updateNum() {number1.value++}return {number1,updateNum,}},
}) </script>
刚才强调了说 ref 接收 基本类型的数据,那么它可以接收复杂类型吗,如object
类型等,当然可以
如果给 ref
传入复杂类型,其实它是调用 reactive
来实现的
reactive 接收一个普通对象然后返回该普通对象的响应式代理对象
其底层就是使用
Proxy
进行代理
target
:要使用 Proxy
包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)handler
:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p
// 模拟 Vue data
let data = {msg: '',age: '',
}
// 模拟 Vue 的一个实例
// Proxy 第一个
let vm = new Proxy(data, {// get() 获取值// target 表示需要代理的对象这里指的就是 data// key 就是对象的 键get(target, key) {return target[key]},// 设置值// newValue 是设置的值set(target, key, newValue) {// 也先判断下是否和之前的值一样 节省性能if (target[key] === newValue) return// 进行设置值target[key] = newValuedocument.querySelector('#app').textContent = target[key]},
})
import { defineComponent, reactive } from 'vue'
setup() {let obj = reactive({name: '小浪',age: 21,})return {obj,}
}
控制台输出返回的 Proxy
对象吧
数据都在 target
中,在模板使用直接 {{obj.name}}
即可修改直接修改 obj[name] = ‘xxx’
操作代理对象,obj中的数据也会随之变化,同时如果想要在操作数据的时候,界面也要跟着重新更新渲染,那么也是操作代理对象
响应式的数据是深层次的(递归深度响应式)。对于多层嵌套的数据也是响应式的
setup() {let obj = reactive({name: '小浪',age: 21,phone: {p_name: '小米',p_apps: {app_name: '小米运动',},},})function upadateName() {obj.phone.p_apps.app_name = '掘金'}console.log(obj)return {obj,upadateName,}
},
setup() {let obj = ref({name: '小浪',age: 21,})console.log(obj)return {obj,}
}
由此可见,ref
方法传入对象是使用 reactive
来进行操作的
这个方法可以把 reactive
响应式对象,转化为 普通对象,普通对象的每个属性都是 Ref
对象,这样的话保证了 reactive
的每个属性还是响应式的,我们还可以把每个属性进行分解使用,这样在组件就不用 obj[属性] ,代码量减轻了,yyds
setup() {const user = reactive({name: '小浪',age: 21,})let userObj = toRefs(user)console.log(userObj)return {}
}
可以看见 name
和 age
已经变成了 Ref
对象
我们可以解构 出 name
和 age
单独使用
setup() {const user = reactive({name: '小浪',age: 21,})let userObj = toRefs(user)return {...userObj,}
}
还有一个 toRef
方法,它的作用和 toRefs
差不多,但是它只能把响应式对象/普通对象的某一个属性变为 Ref
对象
可以用来为源响应式对象上的
property
性创建一个ref
。然后可以将ref
传递出去,从而保持对其源property
的响应式连接。
export default {setup(props) {useSomeFeature(toRef(props, 'foo'))}
}
function useSomeFeature(foo: Ref) {// ...
}
拷贝了一份新的数据值单独操作, 更新时相互不影响
当您要将 prop
的 ref
传递给复合函数时,toRef
很有用
可以从官方文档看出,用于在于组件之前的传递数据 从 props
拿出 'foo'
属性给复合函数,复合函数 useSomeFeature
,接收的参数 foo
为 Ref
类型,刚好可以使用toRef
来进行转化
在Vue3
中使用computed
和Vue2.X
有些不同,这里 computed
是一个方法
首先还是得导入
computed
方法
import { defineComponent, computed } from 'vue'
复制代码
参数为一个回调 默认为
get
<template><div class="box"><input type="text" v-model="name" /><br /><input type="text" v-model="age" /><br /><input type="text" v-model="getInfo" /></div>
</template>
复制代码
setup() {let name = ref('小浪')let age = ref(21)
//计算属性let getInfo = computed(() => {return `我的名字:${name.value},今年${age.value},请多多指教`})return {name,age,getInfo,}
}
复制代码
这里没有实现 set
方法,所以修改下面没有用
参数为一个对象 在这里写
get
set
模板和上面一样
setup() {let name = ref('小浪')let age = ref(21)let getInfo = computed({// get 方法get() {return `${name.value},${age.value}`},// set 方法set(val: string) {let arr = val.split(',')name.value = arr[0]age.value = parseInt(arr[1])},})return {name,age,getInfo,}
和 Vue2.X 的 Watch 使用方法差不多
介绍
watch(data,handler,object)
1.data
:可以是返回值的 getter
函数,也可以是 ref
2.handler
:回调函数
3.object
:可选配置项 { immediate: true }
引入
import { defineComponent, watch } from 'vue'
data
为一个ref
回调函数的参数是 (新值,旧值)
setup() {let name = ref('小浪')let age = ref(21)let watchName = ref('')watch(name, (newName, oldName) => {watchName.value = `我是新姓名${newName}
我是老姓名${oldName}`})return {name,age,watchName,}
},
可以看见页面第三栏没有显示,因为 name
值没有变化,所以就不用改变,watch
的第三个参数是 配置对象,我们在里面可以设置 立即执行 { immediate: true }
就会执行一次 当然这个时候 oldName
为 undefined
watch(name,(newName, oldName) => {watchName.value = `我是新姓名${newName}我是老姓名${oldName}`},{ immediate: true }
)
data
为一个getter
watch(()=>haha,(newName, oldName)=>{// 处理...
})
()=> haha
直接返回一个值,相当于 getter
简写,haha
可以不是响应式数据
data
为多个ref
模板还是之前那个
<template><div class="box"><input type="text" v-model="name" /><br /><input type="text" v-model="age" /><br /><input type="text" v-model="getInfo" /></div>
</template>
我们可以把多个 ref
放进一个数组里面
newNameAndAge
,oldNameAndAge
为一个数组保存着 新 和 旧的 [name,age]
setup() {let name = ref('小浪')let age = ref(21)let watchName = ref('')watch([name, age],(newNameAndAge, oldNameAndAge) => {watchName.value = `new: ${newNameAndAge}old: ${oldNameAndAge}`},{ immediate: true })return {name,age,watchName,}
},
data
为reactive
setup() {let user = reactive({name: '小浪',age: 21,})let watchInfo = ref('')watch(user,(newInfo, oldInfo) => {console.log(newInfo === oldInfo)// true})
}
这里是对象 会出现问题,立即执行后,
如果加上 立即执行 除了第一次 newInfo
为 {name: '小浪',age: 21}
oldInfo
为 undefined
,之后始终返回该对象的当前值
所以 newInfo
= oldInfo
对于这个问题,我们得加上配置对象 {deep: true}
进行深度检测
深度检测还可以判断多重嵌套
watch(user,(newInfo, oldInfo) => {console.log(newInfo === oldInfo) // false},{ deep: true }
)
Vue2.X
对应Vue3
组合API
Vue2.X | Vue3 | |
---|---|---|
beforeCreate | —> | setup() |
created | —> | setup() |
beforeMount | —> | onBeforeMount |
mounted | —> | onMounted |
beforeUpdate | —> | onBeforeUpdate |
updated | —> | onUpdated |
beforeDestroy | —> | onBeforeUnmount |
destroyed | —> | onUnmounted |
activated | —> | onActivated |
deactivated | —> | onDeactivated |
errorCaptured | —> | onErrorCaptured |
onRenderTriggered | ||
onRenderTracked |
可以看出
beforeCreate
和 created
在Vu3还是能正常使用,在Vue3我们可以用更好更快的 setup
代替
on
开头的 生命周期需要 通过 import
导入,在 setup
函数中使用
Vue3
的生命周期 比 Vue2.X
的生命周期快
举个例子: onBeforeMount
比 beforeMount
快 其他同理
还多个两个钩子:
onRenderTriggered
跟踪虚拟 DOM 重新渲染时调用onRenderTracked
当虚拟 DOM 重新渲染被触发时调用Vue2.X
中 Vue
上面的全局API ,比如自定义指令 Vue.directive
,全局组件 Vue.component
在Vue3都进行改变,不再提供 Vue
,而是提供 app
具体改变可以看下面
Vue2.X | Vue3 |
---|---|
Vue.config | app.config |
Vue.config.productionTip | 移除 |
Vue.config.ignoredElements | app.config.isCustomElement |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.globalProperties |
new Vue().$mount(‘#app’) | createApp(App).mount(‘#app’) |
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。