render函数
vue组件定义方法
- 原始方法
<div id="app"> <sth :level=level>标题在此</sth> <template id='plug'> <div> <h1 v-if="level===1"> <slot></slot> </h1> <h2 v-if="level===2"> <slot></slot> </h2> <h3 v-if="level===3"> <slot></slot> </h3> </div> </template> </div>
var app = new Vue({ el: '#app', data:{ level:1 }, components: { 'sth': { props: ['level'], template: '#plug' } } })
- 使用render函数
<div id="app"> <sth :level=level>标题在此</sth> </div>
var app = new Vue({ el: '#app', data: { level: 3 }, components: { 'sth': { props: ['level'], render(createElement) { return creatEelement('h' + this.level, this.$slots.default) //this.$slots.default 子节点数组 } } } })
render函数的第一个参数
第一个参数必须
creatElement(String / Object / Function)
var app = new Vue({ el: '#app', components: { 'sth': { render(createElement) { /* return createElement('div') ---String*/ /* return createElement({ template: '<span></span>' ---Object }) */ var fun = function() { return { template: '<h1></h1>' } } return createElement(fun()) //---Function } } } })
render函数的第二个参数
第二个参数可选,是数据对象,必须是Object
creatElement(第一个参数,第二个参数:Object)
var app = new Vue({ el: '#app', components: { 'sth': { render(createElement) { return createElement({ //第一个参数 template: '<div>内容</div>' }, { //第二个参数——数据对象 只能是Object //类名:布尔 'class': { too: true, foo: false }, style: { color: 'red', fontSize: '18px' }, //正常html特性 attrs: { id: 'aaa', src: 'bbb' }, //原生的dom属性 domProps:{ innerHTML:'<span style="color:blue;font-size="20px">闹心</span>' } }) } } } })
render函数的第三个参数
第三个参数可选,Object / Array 是作为构建函数的子节点
var app = new Vue({ el: '#app', components: { 'sth': { render(createElement) { return createElement('div', [ createElement('h1', '标题1'), //div的子节点 createElement('h4', '标题4') //div的子节点 ]) } } } })
在render函数中使用插槽
<div id="app"> <sth> <p>内容</p> <p>内容</p> <p>内容</p> <h1 slot='header'>标题</h1> <h3 slot='footer'>底部</h3> </sth> </div>
let app = new Vue({ el: '#app', components: { 'sth': { render(createElement) { var header = this.$slots.header var main = this.$slots.default var footer = this.$slots.footer return createElement('div', [ createElement('header', header), //这边的header是虚拟节点--数组 createElement('main', main), createElement('footer', footer) ]) } } } })
在render函数中使用props
<div id="app"> <sth :show='show'></sth> <button @click='change_img'>点击切换</button> {{show}} </div>
let app = new Vue({ el: '#app', data: { show: false }, methods: { change_img() { this.show = !this.show } }, components: { 'sth': { props: ['show'], render(createElement) { var img if (this.show) { img = 'https://w.wallhaven.cc/full/0w/wallhaven-0wpxxr.jpg' } else { img = 'https://w.wallhaven.cc/full/4g/wallhaven-4gyqm3.jpg' } return createElement('img', { attrs: { src: img }, style: { '300px', height: '150px' } }) } } } })
在render函数中使用v-model
<div id="app"> <sth :name='name' v-model='name'></sth> {{name}} </div>
new Vue({ el: '#app', data: { name: '' }, components: { 'sth': { render(createElement) { var self = this return createElement('input', { domProps: { value: self.name }, on: { input(ev) { self.$emit('input', ev.target.value) } //这里的this默认是指向window,需要改变this指向为Vue实例 //input:function(ev){this.$emit('input',ev.target.value)} } }) }, props: ['name'] } } })
在render函数中使用作用域插槽
<div id="app"> <sth> <template scope='prop'> {{prop.text}} {{prop.msg}} </template> </sth> </div>
let app = new Vue({ el: '#app', components: { 'sth': { render(createElement) { return createElement('div', this.$scopedSlots.default({ text: '哈哈哈', msg: 'aaaa' })) } } } })
函数化组件
没有data和this的概念
万能context 上下文对象
<div id="app"> <sth value='aaa'></sth> </div>
let app = new Vue({ el: '#app', components: { 'sth': { props: ['value'], functional: true, //表示当前的vue实例无状态,无实例 render(createElement, context) { return createElement('button', { on: { click() { console.log(context) console.log(context.parent) console.log(context.props.value) } } }, '点击') } } } })