首先要理解如何通过props来进行父子组件之间传值,参考https://segmentfault.com/a/1190000010913794。更多详情查看官网: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 选项,则该对象包含了应当被注入的属性。