基於vue-cli理解render函式
下面的方法都是基於vue-cli來闡述的,首先要理解如何通過props來進行父子元件之間傳值,參考https://segmentfault.com/a/1190000010913794。更多詳情檢視官網: ofollow,noindex">cn.vuejs.org/v2/guide/re…
父元件
<template> <div> <component :my-data="items" :is="currentView"></component> </div> </template> <script> import child from './child' export default { data () { return { items: [1, 2, 3, 4], currentView: child } } } </script> 複製程式碼
一.基本用法
子元件 child.js
export default { props: { myData: Array }, render: function (createElement) { return createElement('h3', this.myData) } } 複製程式碼
注:第一個標籤引數為必填項

二.新增樣式、方法
子元件 child.js
export default { props: { myData: Array }, 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! '); } } } 複製程式碼

或者也可以把內容放在外面
export default { props: { myData: Array }, return createElement('h3', { 'class': { foo: true, bar: false }, style: { color: 'red', fontSize: '18px' } },this.myData) } 複製程式碼

三.陣列迴圈輸出
子元件 child.js
export default { let items = this.myData return createElement('div', Array.apply(null, { length: items.length }).map(function (item, index) { return createElement('h3', items[index]) }) ) } 複製程式碼

四.新增子元素
子元件 child.js
export default { return createElement('div', [// 由createElement函式構建而成的陣列 createElement('h1', '主標'), // createElement函式返回VNode物件 createElement('h2', '副標') ]) } 複製程式碼

五. this.$slots用法
父元件
<template> <div> <component :my-data="items" :is="currentView"> <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> </component> </div> </template> <script> import child from './child' export default { data () { return { items: [1, 2, 3, 4], currentView: child } } } </script> 複製程式碼
子元件 child.js
export default { const {header, footer} = this.$slots const body = this.$slots.default return createElement('div', [ createElement('header', header), createElement('main', body), createElement('footer', footer) ]) } 複製程式碼

六. v-model用法
父元件
<template> <div> <component :name="name" :is="currentView" @input="val=>name=val"></component> <div>你的名字是:{{name}}</div> </div> </template> <script> import child from './child' export default { data () { return { name: '', currentView: child } } } </script> 複製程式碼
子元件 child.js
export default { props: { name: String }, render: function (createElement) { var self = this return createElement('input', { domProps: { value: this.name }, on: { input: function (event) { self.$emit('input', event.target.value) } } }) } } 複製程式碼

七.作用域插槽(獲取子元件資料)
父元件
<template> <div> <child> <template scope="props"> <span>{{props.text}}</span> </template> </child> </div> </template> <script> import child from './child' </script> 複製程式碼
子元件 child.js
export default { props: { name: String }, render: function (createElement) { return createElement('div', [ this.$scopedSlots.default({ text: 'hello world!' }) ]) }, } 複製程式碼

八. 子元件之間傳遞作用域插槽
父元件
<template> <div> <child></child> </div> </template> <script> import child from './child' </script> 複製程式碼
子元件 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: {} } }, components: {child}, methods: { change: function (type) { if (type === 'img') { this.data = { type: 'img', url: 'https://raw.githubusercontent.com/iview/iview/master/assets/logo.png' } } else if (type === 'video') { this.data = { type: 'video', url: 'http://vjs.zencdn.net/v/oceans.mp4' } } else if (type === 'text') { this.data = { type: 'text', 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.url } }) ]) } } // 視訊元件 var VideoItem = { props: ['data'], render: function (createElement) { return createElement('div', [ createElement('p', '視訊元件'), createElement('video', { attrs: { src: this.data.url, controls: 'controls', autoplay: 'autoplay' } }) ]) } } // 純文字元件 var TextItem = { props: ['data'], render: function (createElement) { return createElement('div', [ createElement('p', '純文字元件'), createElement('p', this.data.text) ]) } } 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 選項,則該物件包含了應當被注入的屬性。