理解vue中render函數

參考 segmentfault.com/a/119000001…
更多詳情查看官網:cn.vuejs.org/v2/guide/re…html

父組件vue

<template>
  <div>
    <child :my-data="items" ></child>
  </div>
</template>

<script>
import child from './child'
export default {
  data () {
    return {
      items: [1, 2, 3, 4]
    }
  }
}
</script>
複製代碼

一. 基本用法

子組件 child.jsgit

export default {
  props: {
    myData: Array
  },
  render: function (createElement) {
    return createElement('h3', this.myData)
  }
}
複製代碼

注: 第一個標籤參數爲必填項 類型能夠爲 {String | Object | Function}github

// Object
return createElement({
    template: '<div></div>'//組件選項對象
});
複製代碼
// Function
var func = function() {
    return {template: '<div></div>'}
};
return createElement(func());
複製代碼

二. 添加樣式、方法

export default {
  props: {
    myData: Array
  },
  render: function (createElement) {
   return createElement('h3', {
      'class': {
        foo: true,
        bar: false
      },
      style: {
        color: 'red',
        fontSize: '18px'
      },
      attrs: {
        id: 'my-data'
      },
      on: {
        click: this.handleClick
      }
      domProps: {
        innerHTML: this.myData
      }
   })
  },
  methods: {
    handleClick: function() {
        console.log(' I am data! ');
    }
  }
}
複製代碼

或者也能夠把內容放在外面segmentfault

return createElement('h3', {
    'class': {
      foo: true
    },
},this.myData)}
複製代碼

三.添加子元素

return createElement('div', [ // 由createElement函數構建而成的數組
    createElement('h1', '主標'), // createElement函數返回VNode對象,VNodes必須惟一
    createElement('h2', '副標')
  ])
  // var childNode = createElement('h1', '標題');
  // return createElement('div', [
  //        childNode, childNode  //VNodes必須惟一,渲染失敗
  //    ]);
  // }

複製代碼

四. 數組循環輸出

const items = [1,2,3,4]
  return createElement('div',
    items.map(item=> {
        return createElement('h3', item)
    })
  )

複製代碼

在模板中使用的v-if/v-else同理數組

render: function (createElement) {
  const items = [1,2,3,4]
  if (items.length) {
    return createElement('ul', items.map((item)=> {
      return createElement('li', item)
    }))
  } else {
    return createElement('p', 'No items found.')
  }
}
複製代碼

五. this.$slots用法

父組件bash

<template>
  <div>
    <child>
      <h1 slot="header"><span>About Me</span></h1>
      <p>Here is some page content</p>
      <p slot="footer">Copyright 2016 Evan You</p>
      <p>If I have some content down here</p>
    </child>
  </div>
</template>

<script>
import child from './child'
</script>
複製代碼

子組件 child.jsiview

const {header, footer} = this.$slots
  const body =this.$slots.default
  return createElement('div', [
    createElement('header', header),
    createElement('main', body),
    createElement('footer', footer)
  ])
複製代碼

六. v-model用法

父組件dom

<template>
  <div>
    <child :name="name"  @input="val=>name=val"></child>
    <div>你的名字是:{{name}}</div>
  </div>
</template>

<script>
import child from './child'
export default {
  data () {
    return {
      name: ''
    }
  }
}
</script>
複製代碼

子組件 child.jside

export default {
  props: {
    name: String
  },
  render: function (createElement) {
    return createElement('input', {
      domProps: {
        value: this.name
      },
      on: {
        input: event=> {
          self.$emit('input', event.target.value)
        }
      }
    })
  }
}
複製代碼

七.做用域插槽(獲取子組件數據)

父組件

<template>
    <child>
      <template scope="props">
        <span>{{props.text}}</span>
      </template>
    </child>
</template>
複製代碼

子組件 child.js

export default {
  render: function (createElement) {
    return createElement('div', 
      this.$scopedSlots.default({
        text: 'hello world!'
      })
    )
  },
}
複製代碼

八. 子組件之間傳遞做用域插槽

子組件 child.js

import Vue from 'vue'
export default {
  render: function (createElement) {
    return createElement('div', [
      createElement('children', {
        scopedSlots: {
          default: function (props) {
            return [
              createElement('span', '來自父組件'),
              createElement('span', props.text)
            ]
          }
        }
      })
    ])
  }
}
Vue.component('children', {
  render: function (createElement) {
    return createElement('b',
    this.$scopedSlots.default({
      text: '我是子組件'
    }))
  }
})
複製代碼

九. 函數化組件

父組件

<template>
  <div>
    <child :data="data"></child>
  </div>
</template>

<script>
import child from './child'
export default {
  data () {
    return {
      data: {
          type:'',
          content:''
      }
    }
  },
  components: {child},
  methods: {
    change: function(type) {
      this.data.type=type
      const content = () => {
        switch (type) {
          case 'img':
            return 'https://raw.githubusercontent.com/iview/iview/master/assets/logo.png'
          case 'video':
            return 'http://vjs.zencdn.net/v/oceans.mp4'
          default:
            return '這是一段純文本'
        }
      }
      this.data.content=content()
    }
  },
  mounted: function () {
    this.change('img')
  }
}
</script>
複製代碼

子組件 child.js

// 圖片組件
var ImgItem = {
  props: ['data'],
  render: function (createElement) {
    return createElement('div', [
      createElement('p', '圖片組件'),
      createElement('img', {
        attrs: {
          src: this.data.content
        }
      })
    ])
  }
}
// 視頻組件
var VideoItem = {
  props: ['data'],
  render: function (createElement) {
    return createElement('div', [
      createElement('p', '視頻組件'),
      createElement('video', {
        attrs: {
          src: this.data.content,
          controls: 'controls',
          autoplay: 'autoplay'
        }
      })
    ])
  }
}
// 純文本組件 
var TextItem = {
  props: ['data'],
  render: function (createElement) {
    return createElement('div', [
      createElement('p', '純文本組件'),
      createElement('p', this.data.content)
    ])
  }
}
export default {
  functional: true,
  render: function (createElement, context) {
    function getComponent () {
      var data = context.props.data
      switch (data.type) {
        case 'img':
          return ImgItem
        case 'video':
          return VideoItem
        default:
          return TextItem
      }
    }
    return createElement(
      getComponent(),
      context.data
      // context.children
    )
  }
  //在 2.3.0 或以上的版本中,你能夠省略 props選項,全部組件上的特性都會被自動解析爲 props。
  // props:{
  //    data:Object
  //}, 
}
複製代碼

注: 在添加 functional: true 以後,錨點標題組件的 render 函數之間簡單更新增長 context 參數,this.$slots.default 更新爲 context.children,以後this.data 更新爲 context.props.data

組件須要的一切都是經過上下文傳遞,包括:

  • props:提供全部 prop 的對象
  • children: VNode 子節點的數組
  • slots: 返回全部插槽的對象的函數
  • data:傳遞給組件的數據對象,做爲 createElement 的第二個參數傳入組件
  • parent:對父組件的引用
  • listeners: (2.3.0+) 一個包含了全部在父組件上註冊的事件偵聽器的對象。這只是一個指向 data.on 的別名。
  • injections: (2.3.0+) 若是使用了 inject 選項,則該對象包含了應當被注入的屬性。
相關文章
相關標籤/搜索