上一篇我们讲解了vue中使用 render 函数创建HTML,在创建过程比较复杂,而且模板中的 DOM 结构可读性差。那么这一篇我们主要了解JSX和函数组件
JSX
JSX全称是JavaScript XML,是一种JavaScript语法扩展,用于描述用户界面。其格式比较像是模板语言,但事实上完全是在JavaScript内部实现的。
JSX语法用于简化模板的编写,使得模板的编写变得和普通 DOM 模板一样简单。在 Vue.js中,想要使用 JSX 语法就必须下载 Babel 插件。
将如下 DOM 结构:
<div>
<span>hello,vue</span>
</div>
采用普通 render 函数实现:
createElement(
'div', [
createElement('span', 'Hello,vue')
]
)
采用 JSX 语法的 render 函数实现:
new Vue({
el: '#demo',
render() {
return (
<div>
<span>Hello,vue</span>
</div >
)
}
})
函数式组件
vue中的函数式组件也称为无状态组件,其内部没有任何状态。函数式组件中只接受一个props参数,没有其他参数。
声明函数式组件有两种方式,如下所示:
<template functional>
{{data}}
<template>
//声明为函数式组件
Vue.component('my-component', {
functional: true,
// Props 是可选的
props: {
// ...
}, render: function (createElement, context) {
// ...
}
})
声明函数式组件必须使用functional
关键字,函数式组件的特点是,无状态——函数式组件本身是没有状态的,也就是没有响应式数据;无实例——函数式组件没有实例,也就是没有this上下文
在render
的参数中有一个context
,这个用于函数式的参数传递,它是一个对象,包含如下对象:
- props:提供所有 prop 的对象
- children:VNode 子节点的数组
- slots:一个函数,返回了包含所有插槽的对象
- scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
- data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
- parent:对父组件的引用
- listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
- injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。
函数式组件说到底,也是组件的一种声明方式,属于 render 函数的一种,只不过函数式组件渲染的开销很低,且函数式组件只是一个函数,这种组件声明过程中,只有 props 选项可用,其他选项就算声明了也无法使用。
函数式组件的传递属性和事件
在上面我们提到,函数式组件只有一个 props 选项,在普通方式声明组件时,非props 属性会自动添加到根元素。而函数式组件不行,函数式组件会自动将非 props 属性转化为 prop 属性。除此之外, context
对象的 data 选项中包含所有的非prop 属性和所有的事件监听器,其中属性存放在 attrs 对象中,所有的事件监听器存放在 on 对象中。context
对象的 children 选项中包含所有的子节点 。
通过具体实例了解一下,下列实例是完整的函数式组件实例:
<div id="app">
<h1>hello,vue</h1>
<post-item @click="h1_click" :text="111">
组件
</post-item>
</div>
<script>
Vue.component('PostItem', {
functional: true,
props: ['text'],
render(createElement, context) {
return createElement("button", context.props.text, context.children)
},
})
let vm = new Vue({
el: "#app",
methods: {
h1_click() {
console.log("点击事件");
}
},
})
</script>