点击上方“蓝字”关注我们
作者 | 王冠淇
编辑 | 张婵
概念
组合式 API(Composition API),其本质是为了更方便实现逻辑的组合而产生的。
Vue2 中存在的问题
Vue2 中如果想给所有组件都添加公共逻辑,比如果添加防抖,主要的实现方式是利用 Mixins来注入,但是这种实现有一个弊端,光看模板很难分清一个属性是从哪来的,而且一旦这种注入的逻辑增多,无论是对代码阅读,还是维护来说,都有较大的困难。
Vue2 中的代码
首先先看一下:
constApp={
template:`
{{message}}
`,
data(){
return{
message:'Hello Vue 3!!'
}
},
methods:{
click(){
console.log('click ....',this.message)
this.message =this.message.split('').reverse().join('')
}
}
}
let vm =newVue({
render: h => h(App)
}).$mount('#app')
经典的 Vue API 可以归纳成 options API,是基于配置的方式声明逻辑的 API,但是业务逻辑一旦复杂的话,就会出现一定的问题,一旦逻辑复杂你就不能给他写成一大坨,就需要考虑哪些部分需要抽离出来,需要考虑共有逻辑,不然程序维护难度太大。
Vue3 中的代码
第一段逻辑是尤大的逻辑鼠标位置监听逻辑:
function useMouse(){
const state = reactive({
x:0,
y:0
})
const update = e =>{
state.x = e.pageX
state.y = e.pageY
}
onMounted(()=>{
window.addEventListener('mousemove', update)
})
onUnmounted(()=>{
window.removeEventListener('mousemove', update)
})
return toRefs(state)
}
我们还想组合另外一段逻辑,比如随时刷新的时间逻辑:
function useOtherLogic(){
const state = reactive({
time:''
})
onMounted(()=>{
setInterval(()=>{
state.time =newDate()
},1000)
})
return toRefs(state)
}
在实际的工作中我们可以认为这两个逻辑可能被很多组件复用,如果你使用 Mixin 将会十分麻烦,但是如果利用组合式 API,只需引入这两段逻辑即可。
constMyComponent={
template:`
x:{{ x }} y:{{ y }} z:{{ time }}
`,
setup(){
const{
x,
y
}= useMouse()
// 与其它函数配合使用
const{
time
}= useOtherLogic()
return{
x,
y,
time
}
}
}
createApp().mount(MyComponent,'#app')
API 介绍
我们先看看 Vue3 的基础 API 都有哪些?
const{
createApp,
reactive,// 创建响应式数据对象
ref,// 创建一个响应式的数据对象
toRefs,// 将响应式数据对象转换为单一响应式对象
isRef,// 判断某值是否是引用类型
computed,// 创建计算属性
watch,// 创建watch监听
// 生命周期钩子
onMounted,
onUpdated,
onUnmounted,
}=Vue
setup 使用 composition API 的入口
setup 函数会在 beforeCreate 之后 created 之前执行
setup(props,context){
console.log('setup....',)
console.log('props',props)// 组件参数
console.log('context',context)// 上下文对象
}
reactive
reactive() 函数接受一个普通对象 返回一个响应式数据对象
const state = reactive({
count:0,
plusOne: computed(()=> state.count +1)
})
ref 与 isRef
ref 将给定的值(确切的说是基本数据类型 ini 或 string)创建一个响应式的数据对象
isRef 其实就是判断一下是不是ref生成的响应式数据对象
toRefs
toRefs 可以将 reactive 创建出的对象展开为基础类型
// 如果不用toRefs
const state = reactive({
count:0,
plusOne: computed(()=> state.count +1)
})
return{
state
}
// 模板渲染要这样写
template:`
count is {{ state.count }}
plusOne is {{ state.plusOne }}
`
// 我们再看看用了toRefs
const state = reactive({
count:0,
plusOne: computed(()=> state.count +1)
})
return{
...toRefs(state)
}
// 模板渲染要这样写
template:`
count is {{ count }}
plusOne is {{ plusOne }}
`
watch 定义监听器
同 Vue2 只是写法略有不同:
watch(()=> state.count *2, val =>{
console.log(`count * 2 is ${val}`)
})
effect 副作用函数
响应式对象修改会触发这个函数:
effect(()=>{
console.log('数值变化了..',state.count)
})
effect 是响应式的副产物,在 get 的时候收集 effect,并在 set 时候触发,和 Vue2 中 dep.notify() 类似。
computed 计算属性
同 Vue2:
const state = reactive({
count:0,
plusOne: computed(()=> state.count +1)
})
生命周期钩子 Hooks
Vue2 | Vue3 |
beforeCreate | setup(替代) |
created | setup(替代) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
Vue3 中的数据绑定
最后,再来分别看一下 Vue2 和 Vue3 中针对数据双向绑定绑定分别做的处理。
Vue2 中数据绑定是基于 Object.definedProperty 实现的,这会产生一些问题,其中最主要的就是性能问题,在 data 中数据嵌套层数过多的时候尤为明显。而且这个方法无法监听数组变化,所以 Vue2 中不得不对数组的变态方法进行了重写。
而在 Vue3 中,数据的双向绑定使用了 ES6 中的 Proxy,同时利用 WeakMap 进行缓存,在性能上面有了较大的提升。
使用 Object.defineProperty 无法监听到新增属性,但是使用 Proxy 是可以监听到的。对比上面两段代码可以发现有以下几点不同:
Object.defineProperty监听的是对象的每一个属性,而 Proxy 监听的是对象自身;
使用 Object.defineProperty 需要遍历对象的每一个属性,对于性能会有一定的影响;
Proxy 对新增的属性也能监听到,但 Object.defineProperty 无法监听到。
其他
另外随着 Vue3 rc 的推出,尤大在直播中提到了 vite。参考 snowpack 专门为 Vue3 开发的打包工具,其描述是:针对 Vue 单页面组件的无法打包开发服务器,可以直接在浏览器运行请求 Vue 文件。
但是和 webpack 比目前功能上还略有不足。并不能完全替代 webpack。
点击【】查看 Vue3 API 文档
猜你喜欢
通过双叉十字模型判断股票买入点位 | 金融科技之量化策略研究课题报告(上)基于时间序列 ARIMA 模型预测股票收盘价 | 金融科技之量化策略研究课题报告(下)建信金科大咖访谈:数字时代,如何稳步迈上智慧经营之路?一个输入框你要做一周? 觉得不错,点个在看