写在前文vue3.2不久前发布,那么对于处于一线的前端工程师,有必要将vue2升级到vue3,迎接全新出现的composition API?
安装最新的@vue/cli
npm install -g @vue/cli
然后使用命令行
vue create hello-vue3 项目名称
<template>
<div>
<el-button @click="add">Add </el-button>
<div v-for="(item,index) in listArray" :key="index">
<el-input v-model="item.value" placeholder="请输入内容" class="item"></el-input>
<i class="el-icon-close" @click="remove(index)"></i>
</div>
</div>
</template>
我们来使用vue3的组合式api也是就是composition API来实现上述功能
<script>
import {ref} from "vue"
export default {
setup() {
//初始化数组
const listArray = ref([{value:1},{value:2},{value:3}])
//add
const add = ()=>{
listArray.value.push({value:""})
}
//remove
const remove =(index)=>{
console.log(index)
listArray.value.splice(index,1)
}
console.log(listArray.value)
return {listArray,add,remove}
},
}
</script>
相较于vue2的options-api来说,
我们对setup和ref做一个总结
setup函数是一个生命周期钩子对应的其实是vue2中的beforeCreate和create,并且他是vue3的composition API的入口函数,在vue3 我们通过这个函数来定义vue2中的data,methods,watch,computed属性,setup函数必须有返回值,必须返回一个对象,对象里包含所有在template模板中需要使用到的属性。
ref
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value。
取值和赋值的时候要通过.value方法去拿,但是template却不使用.value,steup接收两个参数props和context,在js里这个形参代表上下文,暴露组件的property,后者可以拿到
有的人不喜欢这种通过.value还有返回多个值出去在模板或在setup里使用,我们可以使用reative()
用data 将我们需要返回的属性和方法包裹起来再返回
<script>
import {reactive} from "vue"
export default {
setup(props,context) {
console.log(props)
console.log(context)
const data = reactive({
listArray:[{value:1},{value:2},{value:3}],
add:()=>{
data.listArray.push({value:''})
},
remove:(index)=>{
data.listArray.splice(index,1)
}
})
return {data}
},
}
</script>
但是这样有一个问题,在模板中使用,我们需要通过data.xxx来调用属性和方法,
我们很自然很想到能否对他解构赋值,
我们可以通过toRefs()将data元素解构,这样的话,我们直接拿到属性和方法。
<template>
<div>
<el-button @click="add">Add </el-button>
<div v-for="(item,index) in listArray" :key="index">
<el-input v-model="item.value" placeholder="请输入内容" class="item"></el-input>
<i class="el-icon-close" @click="remove(index)"></i>
</div>
</div>
</template>
<script>
import {reactive,toRefs} from "vue"
export default {
setup(props,context) {
// //初始化数组
const data = reactive({
listArray:[{value:1},{value:2},{value:3}],
add:()=>{
data.listArray.push({value:''})
},
remove:(index)=>{
data.listArray.splice(index,1)
}
})
const result = toRefs(data)
return {...result}
},
}
</script>
Vue3的生命周期
正如官方文档所说,setup()取代之前的beforeCreate()和created生命周期函数,其余生命周期函数放在setup()实现。
computed与watch
computed
接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象。或者,接受一个具有 get 和 set 函数的对象,用来创建可写的 ref 对象。
const count = ref(1)
const count2 = ref(2)
const plusOne = computed(()=> count.value+1)
console.log('plusOne:'+plusOne.value)//2
//plusOne.value++
const plusTwo = computed({
get:()=>count2.value+1,
set:val=>{
count2.value = val-1
}
})
console.log('plusTwo:'+plusTwo.value)//3
console.log(plusTwo.value++)//3
watch
为了根据响应式状态自动应用和重新应用副作用,我们可以使用 watchEffect 方法。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> logs 0
setTimeout(() => {
count.value++
// -> logs 1
}, 100)
watch API 完全等同于组件侦听器 property。watch 需要侦听特定的数据源,并在回调函数中执行副作用。默认情况下,它也是惰性的,即只有当被侦听的源发生变化时才执行回调。
-
与 watchEffect 比较,
watch允许我们:- 懒执行副作用;
- 更具体地说明什么状态应该触发侦听器重新运行;
- 访问侦听状态变化前后的值。
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
// 直接侦听ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
但是从设计上相较于React hooks函数式编程对react 16.8以往的class 升级,从语法上我觉得不够简洁,以后会写篇文章对比下,vue 3 composition API生命周期函数依然存在,各种ref api,多了选择,但是也给代码风格统一带来了困难,options API确实存在种种问题,但是也保证了下限。我认为对于目前的vue2项目可以尝试@vue/composition-api,不妨自己动手写下看看效果如何,再考虑是否对项目进行大版本升级。