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


    好家伙,

     

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

    嘶,看不太懂,研究一下
     

    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.方法返回方法

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

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

     

    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()
    复制代码

    成功执行

     

    2.3.回到项目

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

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

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

     

    同样,执行成功了

     

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

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

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

     

    3.代码分析

     

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

     

     来看这串代码

    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等方法执行创建虚拟节点,返回

     

     

  • 相关阅读:
    使用element-ui组件库上传文件及自定义上传文件(包含多文件上传及自定义上传携带其他参数)
    什么?又来看驱动的过程了?是滴,必需滴--I2C设备的注册过程(小白篇)
    Qt应用开发(进阶篇)——线程 QThread
    Docker篇-(1)-Docker简介
    热点参数流控(Sentinel)
    在ubuntu 20.04中通过vscode搭建ESP32-S3的开发环境
    大数据Flink(七十一):SQL的时间属性
    【一起学数据结构与算法】Java实现双链表
    4.物联网射频识别,RFID开发【智能门禁项目】
    docker搭建Hadoop 3节点及N节点集群完整教程
  • 原文地址:https://www.cnblogs.com/FatTiger4399/p/17704272.html