美文网首页
学习Vue之路——render函数

学习Vue之路——render函数

作者: 小螃蟹_5f4c | 来源:发表于2018-12-27 17:12 被阅读0次

    render函数简而言之就是用js的方式来创建html 类似jQuery里面的创建一个字符串 然后append到dom上(我的理解)
    Vue 通过建立一个虚拟 DOM 对真实 DOM 发生的变化保持追踪。请仔细看这行代码

    return createElement('h1', this.blogTitle)
    

    createElement 到底会返回什么呢?其实不是一个实际的 DOM 元素。它更准确的名字可能是 createNodeDescription,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,及其子节点。我们把这样的节点描述为“虚拟节点 (Virtual Node)”,也常简写它为“VNode”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。

    createElement创建虚拟dom的参数

    // @returns {VNode}
    createElement(
      // {String | Object | Function}
      // 一个 HTML 标签字符串,组件选项对象,或者
      // 解析上述任何一种的一个 async 异步函数。必需参数。
      'div',
    
      // {Object}
      // 一个包含模板相关属性的数据对象
      // 你可以在 template 中使用这些特性。可选参数。
      {
        'class': {
        foo: true,
        bar: false
      },
      // 和`v-bind:style`一样的 API
      // 接收一个字符串、对象或对象组成的数组
      style: {
        color: 'red',
        fontSize: '14px'
      },
      // 普通的 HTML 特性
      attrs: {
        id: 'foo'
      },
      // 组件 props
      props: {
        myProp: 'bar'
      },
      // DOM 属性
      domProps: {
        innerHTML: 'baz'
      },
      // 事件监听器基于 `on`
      // 所以不再支持如 `v-on:keyup.enter` 修饰器
      // 需要手动匹配 keyCode。
      on: {
        click: this.clickHandler
      },
      // 仅用于组件,用于监听原生事件,而不是组件内部使用
      // `vm.$emit` 触发的事件。
      nativeOn: {
        click: this.nativeClickHandler
      }
      },
    
      // {String | Array}
      // 子虚拟节点 (VNodes),由 `createElement()` 构建而成,
      // 也可以使用字符串来生成“文本虚拟节点”。可选参数。
      [
        '先写一些文字',
        createElement('h1', '一则头条'),
        createElement(MyComponent, {
          props: {
            someProp: 'foobar'
          }
        })
      ]
    )
    

    官网例子:

    var getChildrenTextContent = function (children) {
      return children.map(function (node) {
        return node.children
          ? getChildrenTextContent(node.children)
          : node.text
      }).join('')
    }
    
    Vue.component('anchored-heading', {
      render: function (createElement) {
        // 创建 kebab-case 风格的ID
        var headingId = getChildrenTextContent(this.$slots.default)
          .toLowerCase()
          .replace(/\W+/g, '-')
          .replace(/(^\-|\-$)/g, '')
    
        return createElement(
          'h' + this.level,
          [
            createElement('a', {
              attrs: {
                name: headingId,
                href: '#' + headingId
              }
            }, this.$slots.default)  //使用了插槽接收内容,也可以使用作用域插槽
          ]
        )
      },
      props: {
        level: {
          type: Number,
          required: true
        }
      }
    })
    

    调用这个新创建的组件的使用:

    <anchored-heading :level="2">Hello world!</anchored-heading>
    

    渲染出来的组件如果用template来实现应该为:

    <h2>
      <a name="hello-world" href="#hello-world">
        Hello world!
      </a>
    </h2>
    

    VNodes 必须唯一
    组件树中的所有 VNodes 必须是唯一的。这意味着,下面的 render function 是无效的:

    render: function (createElement) {
      var myParagraphVNode = createElement('p', 'hi')
      return createElement('div', [
        // 错误-重复的 VNodes
        myParagraphVNode, myParagraphVNode
      ])
    }
    

    如果你真的需要重复很多次的元素/组件,你可以使用工厂函数来实现。例如,下面这个例子 render 函数完美有效地渲染了 20 个相同的段落:

    render: function (createElement) {
      return createElement('div',
        Array.apply(null, { length: 20 }).map(function () {
          return createElement('p', 'hi')
        })
      )
    }
    

    使用 JavaScript 代替模板功能

    只要在原生的 JavaScript 中可以轻松完成的操作,Vue 的 render 函数就不会提供专有的替代方法。比如,在 template 中使用的 v-if 和 v-for

    <ul v-if="items.length">
      <li v-for="item in items">{{ item.name }}</li>
    </ul>
    <p v-else>No items found.</p>
    

    会使用render这样写:

    props: ['items'],
    render: function (createElement) {
      if (this.items.length) {
        return createElement('ul', this.items.map(function (item) {
          return createElement('li', item.name)
        }))
      } else {
        return createElement('p', 'No items found.')
      }
    }
    

    render不支持v-model 需要自己实现该逻辑

    createElement这样写起来超级不方便有木有 所以在项目中使用jsx语法会特别方便
    jsx语法大致是会将<开头的解析成html,将{}解析成js具体可百度
    模板:

    <ul v-if="items.length">
      <li v-for="item in items">{{ item.name }}</li>
    </ul>
    <p v-else>No items found.</p>
    

    会使用jsx格式的render这样写:

    render: function (h) {
      if (this.items.length) {
        return <ul>
              this.items.map((item)=>{
                return <li>{item.name}</li>
              })
            </ul>
      } else {
        return <p>No items found.</p>
      }
    }
    

    之前第一次接触vue项目的时候就是跟着别人做,直接把参考项目的格式复制过来也不知道意思。


    image.png

    这是当时做的项目的其中一个表格中的某个数据要做成a标签形式的 可以点击的那种。

    OK啦!!!


    相关文章

      网友评论

          本文标题:学习Vue之路——render函数

          本文链接:https://www.haomeiwen.com/subject/gdtdlqtx.html