使用Vue3开发TodoMVC
最近在学习Vue3.0的一些新特性,就想着使用Vue3来编写一个todoMVC的示例。本示例是模仿官网的TodoMVC,但是本示例中所有代码都是使用了Vue3的语法。
功能上基本上实现了,不过官方的示例上使用了Local Storage本地缓存来缓存数据,我在本示例中没有使用。另外ui样式我没有完全还原,也算是偷下懒吧。
官网示例:https://cn.vuejs.org/v2/examples/todomvc.html
先来看一下效果
开发中的几个问题
主要用到Vue3的conposition API有:ref, reactive, computed, watchEffect, watch, toRefs, nextTick,
功能我就不细讲了,后面会附上完整代码,主要讲几点在开发过程中遇到的问题,也是Vue3中的一些小改动的问题。
1.列表item的input输入框自动获取焦点
在官网示例中是使用了自定义指令去完成的,先自己定义一个自定义指令,之后再在input标签中去使用
directives: {
"todo-focus": function(el, binding) {
if (binding.value) {
el.focus();
}
}
}
而我在本例中想使用ref来获取dom元素,从而触发input的onfocus事件。
我们知道在Vue2.x中可以使用this.$refs.xxx来获取到对应的dom元素,可是Vue3.0中是没办法使用这种方法去获取的。
查阅了Vue3.0官方文档之后,发现Vue3对ref的使用做了修改。
- Vue2:
- Vue3:
获取DOM元素
2. 在v-for中获取ref
而对在v-for中使用ref,Vue3不再在 $ref 中自动创建数组,而是需要用一个函数来绑定。(参考文档:https://composition-api.vuejs.org/zh/api.html#模板-refs)
//Vue2
export default {
data() {
return {
itemRefs: []
}
},
methods: {
setItemRef(el) {
this.itemRefs.push(el)
}
}
}
//Vue3
import { ref } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
itemRefs.push(el)
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
itemRefs,
setItemRef
}
}
}
在本例中使用了另一种写法,也是一样。
setup() {
const editRefList = ref([]);
watchEffect(async () => {
if (state.itemInputValue) {
await nextTick();
editRefList.value[state.currentTodoId].focus();
}
});
return {editRefList}
}
3. nextTick的使用
在Vue2中我们会这样使用nextTick
this.$nextTick(()=> {
//获取更新后的DOM
})
而在Vue3中这样使用
import { createApp, nextTick } from 'vue'
const app = createApp({
setup() {
const message = ref('Hello!')
const changeMessage = async newMessage => {
message.value = newMessage
// 这里获取DOM的value是旧值
await nextTick()
// nextTick 后获取DOM的value是更新后的值
console.log('Now DOM is updated')
}
}
})
4. watchEffect 和 watch
(1)watchEffect
vue3中新增了watchEffect的方法,也是可以用来监听数据。watchEffect() 会立即执行传入的函数,并响应式侦听其依赖,并在其依赖变更时重新运行该函数。
- 基本用法
const count = ref(0)
// 初次直接执行,打印出 0
watchEffect(() => console.log(count.value))
setTimeout(() => {
// 被侦听的数据发生变化,触发函数打印出 1
count.value++
}, 1000)
- 停止侦听
watchEffect() 使用时返回一个函数,当执行这个返回的函数时,就停止侦听。
const stop = watchEffect(() => {
/* ... */
})
// 停止侦听
stop()
(2)watch
watch的写法与vue2稍稍有点不同
watch侦听单个数据源
侦听的数据可以是个 reactive 创建出的响应式数据(拥有返回值的 getter 函数),也可以是个 ref
watch接收三个参数:
参数1:监听的数据源,可以是一个ref获取是一个函数
参数2:回调函数(val, oldVal)=> {}
参数3:额外的配置 是一个是对象时进行深度监听,添加 { deep:true, immediate: true}
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
},
{ deep:true, immediate: true}
)
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
watch侦听多个数据源
在侦听多个数据源时,把参数以数组的形式给 watch
watch([ref1, ref2], ([newRef1, newRef2], [prevRef1, prevRef2]) => {
/* ... */
})
最后
本例也是自己刚接触vue3之后写的,可能写的并不是很好,如果有哪里有错误或者可优化的请多多指导。
完整代码
todos
-
{{ item.content }}