深入理解Vue官方文档梳理之全局API
前端之家收集整理的这篇文章主要介绍了
深入理解Vue官方文档梳理之全局API,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
Vue.extend
配置项data必须为function,否则配置无效。data的合并规则(可以看《》)源码如下:
传入非function类型的data(上图中data配置为{a:1}),在合并options时,如果data不是function类型,开发版会发出警告,然后直接返回了parentVal,这意味着extend传入的data选项被无视了。
我们知道实例化Vue的时候,data可以是对象,这里的合并规则不是通用的吗?注意上面有个if(!vm)的判断,实例化的时候vm是有值的,因此不同于Vue.extend,其实下面的注释也做了说明(in a Vue.extend merge,both should be function),这也是官方文档为何说data是个特例。
另外官方文档所说的“子类”,是因为Vue.extend返回的是一个“继承”Vue的函数,源码结构如下:
Vue.nextTick
既然使用vue,当然要沿着数据驱动的方式思考,所谓数据驱动,就是不要直接去操作dom,dom的所有操作完全可以利用vue的各种指令来完成,指令将数据和dom进行了“绑定”,操作数据不仅能实现dom的更新,而且更方便。
如果浏览器支持Promise,或者用了Promise库(但是对外暴露的必须叫Promise,因为源码中的判断为typeof Promise !== 'undefined'),nextTick返回的就是Promise对象。
{
// do sth
})
Vue执行nextTick的回调采用call的方式cb.call(ctx);ctx就是当前Vue实例,因此在回调中可以直接使用this调用实例的配置。
nextTick可以简单理解为将回调放到末尾执行,源码中如果当前不支持Promise和MutationObserver,那么会采用setTimeout的方式来执行回调,这不就是我们常用的延后执行代码的方式。
举个例子来实际看下:
new Vue({
el: '#app',data: {
a: 1
},mounted: function name(params) {
console.log('start');
this.$nextTick(function () {
console.log('beforeChange',this.$refs.dom.textContent)
})
this.a = 2;
console.log('change');
this.$nextTick(function () {
console.log('afterChange',this.$refs.dom.textContent)
})
console.log('end');
}
})
// 控制台依次打印
// start
// change
// end
// beforeChange 1
// afterChange 2
你估计会有些纳闷,既然都是最后才执行,那为什么beforeChange输出的是1而不是2,这是因为this.a=2背后触发dom更新也是采用nextTick的方式,上面的代码实际执行的顺序是:beforeChange>更新dom>afterChange。
Vue.set
Vue.set( target,key,value ),target不能是 Vue 实例,或者 Vue 实例的根数据对象,因为源码中做了如下判断:
target._isVue阻止了给Vue实例添加属性,ob && ob.vmCount阻止了给Vue实例的根数据对象添加属性。
Vue.delete
如果Vue能检测到delete操作,那么就不会出现这个api。如果一定要用delete来删除$data的属性,那就用Vue.delete,否则不会触发dom的更新。
同Vue.set,Vue.delete( target,key )的target不能是一个 Vue 示例或 Vue 示例的根数据对象。源码中的阻止方式和Vue.set相同。
在2.2.0+ 版本中target若为数组,key则是数组下标。因为Vue.delete删除数组实际是用splice来删除,delete虽然能用于删除数组,但位置还在,不能算真正的删除。
Vue.use
Vue.use 源码比较简单,可以全部贴出来。
-1) {
return this
}
// additional parameters
var args = toArray(arguments,1);
args.unshift(this);
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin,args);
} else if (typeof plugin === 'function') {
plugin.apply(null,args);
}
installedPlugins.push(plugin);
return this
};
安装的插件放到了 installedPlugins ,安装插件前通过installedPlugins.indexOf(plugin)来判断插件是否被安装过,进而阻止注册相同插件多次。
插件类型为 object,必须指定 install 属性来安装插件(typeof plugin.install === 'function'),另外插件执行采用plugin.install.apply(plugin,args);,因此 this 访问 object 的其他属性。此处的 args 是由 Vue(args.unshift(this);) 和 Vue.use 传入的除了 plugin 的其他参数(toArray(arguments,1),1 表示从 arguments[1] 开始截取)。
插件类型为 function,安装调用plugin.apply(null,args);,因此在严格模式下插件运行时上下文 this 为 null,非严格模式为 Window。
Vue.compile
和众多 JS 模板引擎的原理一样,预先会把模板转化成一个 render 函数,Vue.compile 就是来完成这个工作的,目标是将模板(template 或 el)转化成 render 函数。
Vue.compile 返回了{render:Function,staticRenderFns:Array},render 可直接应用于 Vue 的配置项 render,而 staticRenderFns 是怎么来的,而且按照官网的例子,Vue 还有个隐藏的配置项 staticRenderFns,先来个例子看看。
' +
'' +
'' +
'
'
)
console.log(compiled.render.toString())
console.log(compiled.staticRenderFns.toString())
// render
function anonymous() {
with(this) {
return _c('div',[_m(0),_c('section',[_v(_s(prop))])])
}
}
// staticRenderFns
function anonymous() {
with(this) {
return _c('header',[_c('h1',[_v("no data binding")])])
}
}