zoukankan      html  css  js  c++  java
  • vue之render基本书写方法

    Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器。

    render 基本写法

    export default {
      name: 'renderTest',
      data() {},
      render: (createElement) => {
        return createElement(tag, data, context)
      },
      props: {},
      methods: {},
      created () {}
      ...
    }
    

    Vue 通过建立一个虚拟 DOM 对真实 DOM 发生的变化保持追踪。
    render函数提供了一个参数createElement(可以简写为h), 用来生成DOM, 其有三个参数:

    • 第一个参数: {String | Object | Function}, 必要参数,一个 HTML 标签字符串,组件选项对象,或者一个返回值类型为 String/Object 的函数
    • 第二个参数: {Object},可选参数,一个包含模板相关属性的数据对象,这样,您可以在 template 中使用这些属性。
    • 第三个参数: {String | Array},可选参数, 子节点 (VNodes),由 createElement() 构建而成, 或使用字符串来生成“文本节点”。

    数据对象详解

    {
      // 和`v-bind:class`一样的 API
      '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
      },
      // 自定义指令。注意,您无法对绑定中的 `oldValue` 赋值
      // Vue 会为您持续追踪
      directives: [
        {
          name: 'my-custom-directive',
          value: '2',
          expression: '1 + 1',
          arg: 'foo',
          modifiers: {
            bar: true
          }
        }
      ],
      // Scoped slots in the form of
      // { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: props => createElement('span', props.text)
      },
      // 如果组件是其他组件的子组件,需为插槽指定名称
      slot: 'name-of-slot',
      // 其他特殊顶层属性
      key: 'myKey',
      ref: 'myRef'
    }
    

    v-if 、 v-for 与 v-model
    render 函数中没有与v-if 、 v-for 、v-model 相应的 api, 必须自己来实现相应的逻辑

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

    完整示例
    renderTest组件

    export default {
      name: 'renderTest',
      data() {
        return {
        }
      },
      render: function (createElement) {
    
        return createElement(
          'h' + this.level,
          {
            on: {
              click: this.clickHandler
            }
          },
          [
            createElement('a', {
              attrs: {
                href: '##'
              }
            }, this.$slots.default)
          ]
        )
      },
      props: {
        level: {
          type: Number,
          required: true
        }
      },
      methods: {
        clickHandler () {}
      }
    }
    

    使用组件

    <renderTest :level="1">
      <button> Hello world!</button>
    </renderTest>
    

    组件中自定义render(函数式组件)

    render组件

    export default {
      name: 'renderTest',
      functional: true,
      props: {
        render: Function,
        item: String,
        index: Number
      },
      render: (h, ctx) => {
        const params = {
          item: ctx.props.item,
          index: ctx.props.index
        }
        return ctx.props.render(h, params)
      }
    }
    

    我们将组件记为 functional,这意味它无状态(没有 data),无实例(没有 this 上下文)。
    在添加 functional: true 之后,组件的 render 函数之间将增加 ctx 参数
    组件需要的一切都是通过 ctx 传递,包括:

    • props: 提供 props 的对象
    • children: VNode 子节点的数组
    • slots: slots 对象
    • data: 传递给组件的 data 对象
    • parent: 对父组件的引用

    list组件

    <template>
    <ul class="bs-list left" style="200px;">
      <li v-for="(item, i) in listDate" class="list-item" :key="i">
        <span>{{item}}</span>
        <renderTest v-if="renderfun" :item="item" :index="i" :render="renderfun"></renderTest>
      </li>
    </ul>
    </template>
    <script>
    import renderTest from './renderTest.js'
    export default {
      name: 'lists',
      components: { renderTest },
      props: {
        listDate: {
          type: Array
        },
        renderfun: {
          type: Function,
          default() {
            return () => false
          }
        }
      }
    }
    </script>
    

    使用组件

    <template>
      <div class="text">
         <lists :listDate="listDate" :renderfun="renderfun"></lists>
      </div> 
    </template>
    <script>
    import lists from './lists.vue'
    export default {
      name: 'text',
      components: { lists },
      data() {
        return {
          listDate: [ 'list item 1', 'list item 2', 'list item 3', 'list item 4', 'list item 5' ],
          renderfun: (h, ctx) => {
            return h('div', {
              style: {display: 'inline-block', float: 'right'}
            }, [
              h('button', {
                class: ['btn-primary'],
                on: {
                  click: () => {
                    this.listDate.splice(ctx.index, 1)
                  }
                }
              }, '删除')
            ])
          }
        }
      }
    }
    </script>
    

    JSX使用

    安装babel依赖
    npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-env --save-dev

    .babelrc 文件配置

    {
      "presets": ["env"],
      "plugins": ["transform-vue-jsx"]
    }
    

    书写格式

    render (h) {
      return (
        <div
          // 普通的属性
          id="foo"
          // DOM 属性,添加前缀`domProps`
          domPropsInnerHTML="bar"
          // 事件监听,添加前缀 `on` or `nativeOn`
          onClick={this.clickHandler}
          nativeOnClick={this.nativeClickHandler}
          // 其他属性
          class={{ foo: true, bar: false }}
          style={{ color: 'red', fontSize: '14px' }}
          key="key"
          ref="ref"
          slot="slot">
        </div>
      )
    }
    

    实例

    export default {
      name: 'renderJSX',
      data() {
        return {
          num: 1
        }
      },
      render() {
        const data = {
          class: ['b', 'c']
        }
        return (<div class = 'div'>
        <span>123</span>
          <button onClick={this.clickHandler} class='btn-primary'>btn</button>
          <span class='a' {...data}>{this.num}</span>
        </div>)
      },
      props: {
        level: {
          type: Number
        }
      },
      methods: {
        clickHandler() {
          this.num++
          console.log('clickHandler')
        }
      },
      created() {}
    }
    

    https://vuefe.cn/v2/guide/render-function.html
    https://github.com/vuejs/babel-plugin-transform-vue-jsx

  • 相关阅读:
    用户管理的设计--3.jquery的ajax实现二级联动
    用户管理的设计--2.新增用户信息实现
    用户管理的设计--1.首页查询功能实现
    使用ajax实现简单的带百分比进度条
    python && java
    es6 modules 和commonjs
    es6 promise
    CSS“隐藏”元素的几种方法的对比
    jquery extend
    html5自定义属性
  • 原文地址:https://www.cnblogs.com/xlys/p/8430531.html
Copyright © 2011-2022 走看看