Vue构造类的选项(二) -- render选项

render属性

  • 字符串模板的代替方案,接收一个createElement方法作为第一个参数用来创建VNode,如果组件是一个函数组件,渲染函数还会接收一个额外的context参数,为没有实例的函数组件提供上下文信息(createElement方法可以通过Vue实例中的$createElement()获得 --> const h = this.$createElement())
    注意:Vue选项中render函数弱存在,则Vue构造函数不会从template选项或通过el选项指定的挂载元素中提取出的HTML模板编译渲染函数

  • 渲染函数中使用插槽

    1. this.$slots访问静态插槽的内容(即使得组件能够使用插槽),每个插槽都是一个VNode数组
    render: function (createElement) {
          
          
      // `<div><slot></slot></div>`
      return createElement('div', this.$slots.default)  
    }
    
    1. this.$scopedSlots访问作用域插槽,每个作用域插槽都是一个返回若干VNode的函数
    props: ['message'],
    render: function (createElement) {
          
          
      // `<div><slot :text="message"></slot></div>`
      return createElement('div', [
        this.$scopedSlots.default({
          
          
          text: this.message
        })
      ])
    }
    
    1. 如果要用渲染函数想子组件中传递作用域插槽(使用子组件的作用域插槽),可以利用VNode数据对象中的scopedSlots字段
    render: function (createElement) {
          
          
      // `<div><child v-slot="props"><span>{
          
          { props.text }}</span></child></div>`
      return createElement('div', [
        createElement('child', {
          
          
          // 在数据对象中传递 `scopedSlots`
          // 格式为 { name: props => VNode | Array<VNode> }
          scopedSlots: {
          
          
            default: function (props) {
          
          
              return createElement('span', props.text)
            }
          }
        })
      ])
    }
    
  • 数据对象(createElement第二个(可选)参数)

    {
          
          
      // 接受一个字符串、对象或字符串和对象组成的数组
      'class': {
          
          
        foo: true,
        bar: false,
      },
      // 接受一个字符串、对象,或对象组成的数组
      style: {
          
          
        color: 'red',
        fontSize: '14px'
      },
      // HTML元素属性
      attrs: {
          
          
        id: 'foo'
      },
      // 组件prop
      props: {
          
          
        myProp: 'bar'
      }
      // DOM的属性 (innerHTML、textContent、style、value等)
      domProps: {
          
          
        innerHTML: 'baz'
      },
      // 事件监听
      on: {
          
          
        click: this.clickHandler
      },
      // 仅用于组件,用于监听原生事件,而不是组件内部使用
      // `vm.$emit` 触发的事件。
      nativeOn: {
          
          
        click: this.nativeClickHandler
      },
      // 作用域插槽的格式为
      // { name: props => VNode | Array<VNode> }
      scopedSlots: {
          
          
        default: props => createElement('span', props.text)
      },
      // 如果此组件是其它组件的子组件,需为插槽指定名称
      slot: 'name-of-slot',
      key: 'myKey',
      ref: 'myRef',
    }
    
  • 渲染函数中实现v-model

Vue.component("inp", {
    
    
  props: ["value"],
  render(createElement: Function) {
    
    
    let that = this;
    return createElement("div", {
    
    }, [
      createElement(
        "input",
        {
    
    
          attrs: {
    
    
            value: that.value
          },
          on: {
    
    
            input: function(e: any) {
    
    
              that.$emit("input", e.target.value);
            }
          }
        },
      ),
      createElement("div", that.value)
    ]);
  }
});
<!-- 使用 -->
<inp :value="val" @input="newVal=>val=newVal"></inp>

函数式组件

  • 组件比较简单,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法,实际上它只是接收一些porp。在这样的场景下,可以将组件标记为functional,这意味着它无状态(没有响应式数据),也没有实例(this上下文)
Vue.component('hello-world',{
    
    
  functional:true,
  props:{
    
    
    // ...
  },
  // 为了弥补缺少的实例,提供了第二个参数contxt作为上下文
  render:function( createElement, context ){
    
    
    // ...
  }
})
  • context参数属性
    props:提供所有prop的对象
    children:VNode子节点的数组
    slots:一个函数,返回了包含所有插槽的对象
    scopedSlots:一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
    data: 传递给组件的整个数据对象
    parent:对父组件的引用
    listeners:一个包含了所有父组件为当前组件注册的事件监听的对象,是data.on的一个别名
    injections:如果使用了inject选项,则该对象包含了应当被注入的property

renderError

当render函数遭遇错误时,提供另外一种渲染输出。其错误将会作为第二个参数传递到renderError

new Vue({
    
    
  render (h) {
    
    
    throw new Error('oops')
  },
  renderError (h, err) {
    
    
    return h('pre', {
    
     style: {
    
     color: 'red' }}, err.stack)
  }
}).$mount('#app')

猜你喜欢

转载自blog.csdn.net/qq_36303110/article/details/112189409
今日推荐