Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

好家伙,

 

昨天,在学习vue源码的过程中,看到了这个玩意

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

嘶,看不太懂,研究一下
 

1.上下文

这段出现vue模板编译的虚拟node部分
export function renderMixin(Vue) {     Vue.prototype._c = function () {         //创建标签         return createElement(...arguments)     }     Vue.prototype._v = function (text) { //文本         return createText(text)     }     Vue.prototype._s = function (val) {         return val == null?"":(typeof val ==='object')?JSON.stringify(val):val     }     Vue.prototype._render = function () { //render函数变成 vnode         let vm = this         let render = vm.$options.render         console.log(render,'||this is render')         let vnode = render.call(this)         // console.log(vnode)         return vnode     } } //vnode只可以描述节点  //创建元素 function createElement(tag,data={},...children){     return vnode(tag,data,data.key,children) } //创建文本 function createText(text){     return vnode(undefined,undefined,undefined,undefined,text) } //创建vnode function vnode(tag,data,key,children,text){     return {         tag,         data,         key,         children,         text     } }

 

 

我实在是看不懂这个_render方法在干什么,所以我们开始研究

 

2.冻手尝试

2.1.方法返回方法

写一个简易版本,在一个空白页

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 (显然这会失败,方法返回的方法未定义)

 

2.2.加上方法定义

_c = function () {     //创建标签     return createElement(...arguments) } _v = function (text) { //文本     return createText(text) } _s = function (val) {     return val == null ? "" : (typeof val === 'object') ? JSON.stringify(val) : val }  function createElement(tag, data = {}, ...children) {     return vnode(tag, data, data.key, children) } //创建文本 function createText(text) {     return vnode(undefined, undefined, undefined, undefined, text) } //创建vnode function vnode(tag, data, key, children, text) {     return {         tag,         data,         key,         children,         text     } }  function test() {     return _c('div', _v("张三")) }  test()

成功执行

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 

2.3.回到项目

现在再回到我们的项目
我们知道,渲染函数的_c,_v,_s等方法被定义在Vue的prototype上的

不可能像上述案例这样直接定义在全局

我们在写一个例子,这里用上with()

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 

同样,执行成功了

 

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 所以,我们能看到,正如mdn文档所说,

在这个例子中with()方法拓展了一个test()方法的作用域链

于是,到这里,最难的问题已经解决了

 

3.代码分析

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 

在这里我们知道this指向Vue实例

Vue源码学习(六):(支线)渲染函数中with(),call()的使用以及一些思考

 

 来看这串代码

console.log(this,"||this is this") let vnode = render.call(this)

在 JavaScript 中,.call() 方法可以用于调用函数,并且可以显式地指定函数运行时的作用域(即 this 值)。

 

于是,一切都通畅了

这一大段的代码无非做了这么几件事

1.在Vue的原型上定义_c,_v等节点处理方法

2.(  render.call(this)  )将render方法的作用域指定为this,即Vue实例本身

3.(  with(this)  )此处 with(this) 块中的 this 则指向渲染函数 render 执行时的上下文,也是 Vue 实例

4.随后,_c,_v等方法执行创建虚拟节点,返回

 

 

发表评论

评论已关闭。

相关文章