已同步到个人博客,欢迎访问。
2019.2月,大年三十,Vue在时隔一段时间后发布了新的版本Vue2.6,版本号是Macross(超时空要塞)
真是,不让人过好年啊。学不动了。
吐槽归吐槽,该学还是得学习。相对来说Vue的文档和教程是最平易近人、最易理解的了,而且尤雨溪还亲自发表文章介绍了Vue2.6的更新情况,更没有不跟进的理由了。
最重要的更新之一就是对Slots的语法的更新,Slots对于Vue的组件解耦和分发复用有很重要的意义。旧的语法在2.x版本将获得支持,但是在3.0版本后将被废弃。
这次更新引入了v-slot
来代替原来的slot
和slot-scope
语法
有这样一个组件Comp
:
默认Slot
具名Slot
Hello {{user.firstName}}
原来的语法:
向默认Slot插入的内容
向具名Slot插入的内容
Hi, {{innerUser.lastName}}
{{ msg }}
text slot: {{ msg }}
element slot: {{ msg }}
更新后的语法:
向默认Slot插入的内容
向具名Slot插入的内容
Hi, {{innerUser.lastName}}
{{ msg }}
text slot: {{ msg }}
element slot: {{ msg }}
要注意,v-slot
只能用在元素上,除了一种情况,那就是独占插槽的情况。
当被提供的内容只有默认插槽时,组件的标签才可以被当做插槽的模板来使用。
向默认Slot插入的内容
也可用于作用域插槽:
{{ msg }}
注意,独占插槽下不能出现具名插槽,会导致作用域不明确
向默认Slot插入的内容
向默认Slot插入的内容
只要出现多个插槽,应该始终为所有的插槽使用完整的基于语法
尤雨溪给出了三点原因:
slot-scope
的语义,但是对于大量的学习者而言会在网络上搜索到大量的基于旧的语义的资料,让人困惑,而引入新的区别于slot-scope
的新指令就可以避免这个问题。slot
和slot-scope
代表两种特性就没必要了。原有的语法在多个组件嵌套时会有一个问题,就是不能清晰的判断变量分别是由哪个组件提供的:
{{ foo }} {{ bar }} {{ baz }}
而且,有
提供的foo
却声明在了
上,而是用了新的语法后:
{{ foo }} {{ bar }} {{ baz }}
这是,作用域变量的提供者和声明者是同一个组件,新的语法能够清晰的显示多个作用域变量的关系及其提供者。
普通的slot
是在父组件的渲染函数中生成的,因为此当一个普通的slot
依赖的数据变化时,会首先触发父组件的更新,然后新的slot
内容被传到子组件,触发子组件更新。
而scoped slot
在编译时生成的一个函数,这个函数背传入子组件后会在子组件的渲染函数中被低啊用。这意味着scoped slot
的依赖会被子组件手机,那么当依赖变动时就只会触发子组件的更新了。
在2.6中还引入了一个优化,如果子组件只是用了scoped slot
,那么父组件自身依赖变动时,不会再强制子组件更新。这个优化是的父子组件之间的依赖意识在存在slot的情况下依然完全解耦。
此外,所有使用新的v-slot
的语法的slot
都会编译为scoped slot
,这以为这所有使用新语法的slot
代码都会获得上述的性能优化。
所有的非scoped slot
现在也被以函数的形式暴露在this.$scopedSlots
上。如果是直接用render
函数的用户,现在可以完全抛弃this.$slots
而全部使用this.$scopedSlots
来处理所有的slot
了
这次更新不仅用新的语法v-slot
同一了普通的slot
和scoped slot
的语法,并且针对新的语法在编译性能上进行了优化提升。
虽然在3.0中才会废弃旧的语法,不再有普通的slot
和scoped slot
的区分,并且3.0中this.$slots
将会直接暴露函数,取代 this.$scopedSlots
,但是我认为从2.6起,就应该在项目中使用新的语法代替旧的语法,不仅能更好地迎接3.0的到来,还会获得性能上的提升。
Vue 的内置错误处理机制(组件中的errorCaptured
钩子和全局的errorHandler
配置项)现在也会处理v-on
侦听函数中抛出的错误了。
另外,如果组件的生命周期钩子或者侦听函数中有异步操作现在也可以捕获了,只需要返回一个Promise,来让Vue处理可能存在的异步错误。
例如,在子组件中的button
点击事件:
click() {
return new Promise(resolve => {
throw Error('click')
})
}
父组件中的errorCaptured
钩子函数和全局的errorHandler
配置项中就可以捕获到这个错误:
// 父组件
errorCaptured(e, vm, msg) {
console.log(msg, 999);
}
// 全局错误处理
Vue.config.errorHandler = function(err, vm ,info) {
console.log(info, 'config')
};
如果使用了async
/await
就更加简单,因为async
函数默认返回Promise:
export default {
async mounted() {
// 这里抛出的异步错误会被 errorCaptured 或是
// Vue.config.errorHandler 钩子捕获到
this.posts = await api.getPosts()
}
}
指令的参数现在可以接受动态的JavaScript表达式:
Dynamic slot name
通过这种语法,当表达式的值为null
时,绑定/侦听器会被移除:
2.6开始,所有的编译器都包含了源码的位置信息:
https://cn.vuejs.org/v2/guide/components-slots.html
https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax.md
2.6引入了一个新的全局API,可以用来显示地创建响应式对象:
const reactiveState = Vue.observable({
count: 0
})
Vue内部就是使用这个方法来处理data
函数返回的对象
返回的对象可以直接用于渲染函数和计算属性内,并且在发生改变时触发相应的更新。也可以作为最小化的跨组件状态存储器,用于简单的场景:
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `count is: ${state.count}`)
}
}
用在计算属性内: