之前创建的锚点标题组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法,它只是一个接受参数的函数

在这个例子中,我们标记组件为functional,这意味它是无状态(没有data),无实例(没有this上下文)

一个函数化组件就像这样:

Vue.component('my-component', {
functional: true,
// 为了弥补缺少的实例
// 提供第二个参数作为上下文
render: function (createElement, context) {
// ...
},
// Props 可选
props: {
// ...
}
})
 

注意:在2.3.0之前的版本中,如果一个函数式组件想要接受props,则props选项是必须的,在2.3.0及以上的版本中,你可以省略props选项,所有组件上的属性都会被自动解析为props。

组件需要的一切都是通过上下文传递的,包括:

  • props:提供props对象
  • children:VNode子节点的数组
  • slots:slots对象
  • data:传递给组件的data对象
  • parent:对父组件的引用
  • listeners:(2.3.0+)一个包含了组件上所注册的v-on侦听器的对象。这只是一个指向data.on的别名
  • injections:(2.3.0+)如果使用了inject选项,则该对象包含了应当被注入的属性

在添加functional:true之后,锚点标题组件的render函数之间简单更新增加context参数,this.$slots.default更新为context.children,之后this.level更新为context.props.level.

因为函数化组件只是一个函数,所以渲染开销也低很多。然而,对持久化实例的缺乏也意味着函数化组件不会出现在vue devtools的组件树里。

在作为包装组件时它们也非常有用,比如你需要做这些时:

  • 程序化的在多个组件中选择一个
  • 在将children,props,data传递给子组件之前操作它们。

下面是一个依赖传入props的值的smart-list组件例子,它能代表更多具体的组件:

var EmptyList = { /* ... */ }
var TableList = { /* ... */ }
var OrderedList = { /* ... */ }
var UnorderedList = { /* ... */ }
 
Vue.component('smart-list', {
functional: true,
render: function (createElement, context) {
function appropriateListComponent () {
var items = context.props.items
 
if (items.length === 0) return EmptyList
if (typeof items[0] === 'object') return TableList
if (context.props.isOrdered) return OrderedList
 
return UnorderedList
}
 
return createElement(
appropriateListComponent(),
context.data,
context.children
)
},
props: {
items: {
type: Array,
required: true
},
isOrdered: Boolean
}
})

slots()和children对比

你可能想知道为什么同时需要slots()和children。slots().default不是和children类似的吗?在一些场景中,是这样,但是如果是函数式组件和下面的这样的children呢?

<my-functional-component>
<p slot="foo">
first
</p>
<p>second</p>
</my-functional-component>
对于这个组件,children会给你两个段落标签,而slots().default只会传递第二个匿名段落标签,slots().foo会传递第一个具名段落标签。同时拥有children和slots(),因此你可以选择让组件通过slot()系统分发或者简单的通过children接收,让其他组件去处理。
 
模板编译
你可能有兴趣知道,vue的模板实际上是编译成了render函数。这是一个实现细节,通常不需要关心,但如果你想看看模板的功能是如何编译出来的,你会发现非常有趣,下面是一个使用vue.compile来实时编译模板字符串的简单demo:

<div>
<header>
<h1>I'm a template!</h1>
</header>
<p v-if="message">
{{ message }}
</p>
<p v-else>
No message.
</p>
</div>

render:

function anonymous() {
with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])}
}
staticRenderFns:
_m(0): function anonymous() {
with(this){return _c('header',[_c('h1',[_v("I'm a template!")])])}
}

最新文章

  1. HTML5_02之视频、音频、Canvas
  2. Codeforces Testing Round #10 A. Forgotten Episode
  3. Python字符串的修改以及传参
  4. C#中实现多继承的方法
  5. 下一代大数据系统和4S标准
  6. ElasticSearch大数据分布式弹性搜索引擎使用—从0到1
  7. 行为树(Behavior Tree)实践(1)– 基本概念
  8. 搭建ngrok服务器(ubuntu 14)-- 微信 80端口和IPC备案限制解决方案
  9. SQL-SERVER2008登录错误233
  10. C#使用LitJson解析JSON(转)
  11. 讲解mybaits的标签语法
  12. 成也DP,败也DP(AFO?)
  13. 怎么在Mac上安装Tomcat 7[转载]
  14. matlab练习程序(最小二乘多项式拟合)
  15. jmeter操作练习
  16. Python: 对CSV文件读写 和 Md5加密
  17. http、https 等 常用默认端口号
  18. Hystrix的一个坑,queue中的run方法没有被执行?
  19. DevExpress导出Excel样式设置
  20. Cocoa、Foundation、UIKit、Objective-c、XCode、Interface Builder的概念

热门文章

  1. [转]SSIS cannot convert between unicode and non-unicode string
  2. iOS:quartz2D绘图
  3. PLSQL Developer连接远程Oracle方法(非安装client)
  4. js 修改css属性值
  5. 快速把web项目部署到weblogic上
  6. 【转载】Android控件属性大全
  7. C#秘密武器之特性
  8. ztree3.5.02选中结点时报错
  9. Python中的关键字的用法
  10. python和c#通用一致的des加密采用CBC和PKCS7