Vue3.0全家桶最全入门指南 - 3.x跟2.x的其他差异 (4/4)
本系列文章目录
四、3.x跟2.x的其他差异
ctx属性
对于网上一些其他文档使用
ctx.$router
、ctx.$store
访问router和store的应该小心避坑,注意开发环境和生产环境的差别
vue3.x 开发环境 ctx
开发环境的ctx
,可以看到$router
、$store
、声明的变量和方法等
vue3.x 生产环境 ctx
生产环境的ctx
,$router
、$store
没有了,其他属性也都没有了,不能通过ctx.$router
、ctx.$store
访问router和store,因此ctx可以说对我们没有用,应该避免在代码中使用ctx
执行顺序
vue3.x中会先执行setup
方法,再执行兼容2.x的其他方法,比如data
、computed
、watch
等,
并且在setup
执行过程中,无法访问data
中定义的属性,因为此时还未执行到data
方法
mount挂载
使用mount
挂载的时候
2.x会使用挂载元素的outerHTML
作为template,并替换挂载元素
3.x会使用挂载元素的innerHTML
作为template,并且只替换挂载元素的子元素
this.$el、reactive refs、template refs
2.x可以在组件挂载之后通过this.$el
访问组件根元素
3.x去掉this,并且支持Fragment,所以this.$el
没有存在的意义,建议通过refs
访问DOM
当使用组合式 API 时,reactive refs
和 template refs
的概念已经是统一的。为了获得对模板内元素或组件实例的引用,我们可以像往常一样在 setup()
中声明一个 ref
并返回它
使用reactive refs和template refs
<template>
<div ref="root"></div>
</template>
<script>
import { ref, onMounted, getCurrentInstance } from 'vue'
export default {
setup() {
const vm = getCurrentInstance()
const root = ref(null)
onMounted(() => {
// 在渲染完成后, 这个 div DOM 会被赋值给 root ref 对象
console.log(root.value) // <div/>
console.log(vm.refs.root) // <div/>
console.log(root.value === vm.refs.root) // true
})
return {
root
}
}
}
</script>
在v-for中使用
<template>
<div v-for="(item, i) in list" :key="i" :ref="el => { divs[i] = el }">
{{ item }}
</div>
</template>
<script>
import { ref, reactive, onBeforeUpdate } from 'vue'
export default {
setup() {
const list = reactive([1, 2, 3])
const divs = ref([])
// 确保在每次变更之前重置引用
onBeforeUpdate(() => {
divs.value = []
})
return {
list,
divs
}
}
}
</script>
setup返回普通对象
setup
返回普通对象的时候,会跟reactive
对象一样,具备响应式,执行下面这段代码后会发现普通对象obj1.cnt
也具有响应式了,虽然这样可以行得通,但是为了可读性,防止不了解这个特性的同学误解为非响应式的,建议还是通过reactive
包一下。
<template>
<div>{{ obj1.cnt }}</div>
<div>{{ obj2.cnt }}</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup () {
// 普通对象
const obj1 = {
cnt: 1
}
// 代理对象
const obj2 = reactive({
cnt: 1
})
setInterval(() => {
obj1.cnt++
obj2.cnt++
}, 5000)
return {
obj1,
obj2
}
}
}
</script>
directive指令
vue3.x对指令的生命周期钩子进行了改造,改造后更像3.x普通vue组件的钩子,更方便记忆
// vue2.x
export default {
name: 'YourDirectiveName',
bind(el, binding, vnode, oldVnode) {},
inserted(...) {},
update(...) {},
componentUpdated(...) {},
unbind(...) {}
}
// vue3.x
export default {
beforeMount(el, binding, vnode, oldVnode) {},
mounted(...) {},
beforeUpdate(...) {},
updated(...) {},
beforeUnmount(...) {},
unmounted() {...}
}
render方法修改
vue、react都提供了render
方法渲染html模板,直接使用render
方法的还是比较少,毕竟有template
和JSX
,对于确实需要自定义render
方法渲染模板内容的,具体变动如下:
// vue2.x
export default {
render(h) {
return h('div')
}
}
// vue3.x
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
3.x中移除的一些特性
取消KeyboardEvent.keyCode
在vue3.x中,给keyup
事件配置一个指定按钮的keyCode
(数字)将不会生效,但是依然可以使用别名,例如:
// 无效
<input @keyup.13="handler" />
// 有效
<input @keyup.enter="handler" />
移除 on,on,on,off 和 $once方法
在Vue2.x中可以通过EventBus
的方法来实现组件通信
// 声明实例
var EventBus = new Vue()
Vue.prototype.$globalBus = EventBus
// 组件内调用
this.$globalBus.$on('my-event-name', callback)
this.$globalBus.$emit('my-event-name', data)
在vue3.x中移除了 $on
、$off
等方法,而是推荐使用mitt
方案来代替:
// 声明实例
import mitt from 'mitt'
const emitter = mitt()
// 组件内调用
// listen to all events
emitter.on('*', (type, e) => console.log(type, e))
emitter.on('my-event-name', callback)
emitter.emit('my-event-name', data)
// clearing all events
emitter.all.clear()
移除filters
在vue3.x中,移除了组件的filters
项,可以使用methods
的或者computed
来替代
移除inline-template
在Vue2.x中,在父组件引入子组件时,会用到inline-template
来使子组件的内容也得到展示,参考这里,例如:
<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>
在Vue3中,这个功能将被移除,目前inline-template
使用的并不多,这里就不再过多讲解
后话
虽然vue3.0已经进入rc版本,但是就算vue3.0正式版出来了,3.0相关的生态更新肯定需要一段时间,比如element-ui
、ant-design
、iview
等框架,还有其他开源组件,如果想在正式项目使用的话还是要仔细评估风险,个人建议对vue开源没有依赖的可以先上手vue3.0,有依赖的还是再等一段时间,等生态都支持vue3.0了再去升级,另外对现有项目升级还需要评估工作量。
参考文章
composition-api.vuejs.org/zh/api.html
本系列文章目录
转载自:https://juejin.cn/post/6867123749565497358