Vue提供了一个functional
的布尔值选项,设置为true
可使组件无状态和无实例,也就是没有data
和this
上下文。这样用render
函数返回虚拟节点能够更容易渲染,由于函数化组件只是一个函数,渲染开销要小不少。html
使用函数化组件时,Render函数提供了第二个参数context
来提供临时上下文。组件须要的data
、prop
、slots
、children
、parent
都是经过这个上下文来传递。好比this.level
要改写为context.props.level
,this.$slots.default
改变为context.children
。vue
用函数化组件展现一个根据数据智能选择不一样组件的场景:数组
<p data-height="365" data-theme-id="0" data-slug-hash="mKRKGm" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-函数化组件-根据数据选择组件" class="codepen">See the Pen Vue-函数化组件-根据数据选择组件 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>浏览器
函数化组件主要适用于如下两个场景:babel
children
、props
、data
传递给子组件以前操做它们。为了让Render函数更好地书写和阅读,Vue提供了插件babel-plugin-transform-vue-jsx
来支持JSX语法。app
使用createElement
时,经常使用配置:async
<p data-height="365" data-theme-id="0" data-slug-hash="Vdpwpz" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Vue-createElement" class="codepen">See the Pen Vue-createElement by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>函数
JSX写法:this
<p data-height="300" data-theme-id="0" data-slug-hash="eKvYvm" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Vue-JSX" class="codepen">See the Pen Vue-JSX by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>插件
表格组件的全部的内容(表头和行数据)由两个prop
构成:columns
和data
。二者都是数组,columns
用来描述每列的信息,并渲染在表头<head>
内,能够指定某一列是否须要排序;data
时每一行的数据,由columns
决定每一行里各列的顺序。
为了让排序后的columns
和data
不影响原始数据,给v-table
组件的data
选项添加两个对应的数据,组件全部的操做将在这两个数据上完成,不对原始数据作任何处理。
columns
的每一项是一个对象,其中title
和key
字段是必填的,用来标识这列的表头标题,key
的对应data
中列内容的字段名。sortable
是选填字段,若是值为true
,说明该列须要排序。
v-talbe
组件的prop:columns
和data
的数据已经从父级传递过来,v-table
不直接使用它们,而是使用data
选项的currentColumns
和currentData
。因此在v-table
初始化时,须要把columns
和data
赋值给currentColumns
和currentData
。在v-table
的methods
选项里定义两个方法用来复制,并在mounted
钩子内调用。
map()
是JavaScript数组的一个方法,根据传入的函数从新构造一个新数组。
排序分升序(asc
)和降序(desc
)两种,并且同时只能对一列数据进行排序,与其余列互斥,为了标识当前列的排序状态,在map
列添加数据时,默认给每列都添加一个_sortType
的字段,而且赋值为normal
,表示默认排序(也就是不排序)。
在排序后,currentData
每项的顺序可能都会发生变化,因此给currentColumns
和currentData
的每一个数据都添加_index
字段,表明当前数据在原始数据中的索引。
render(h) { var ths = [], trs = []; return h('table', [ h('thead', [ h('tr', ths) ]), h('tbody', trs) ]) }
这里的h
就是createElement
,只是换了个名称。
表格主题trs
是一个二维数组,数据由currentColumns
和currentData
组成。
先遍历全部的行,而后再每一行内再遍历各列,最终组合出主题内容节点trs
。
若是col.sortable
没有定义,或值为false
,就直接把col.title
渲染出来,不然除了渲染title
,还加了两个<a>
元素来实现升序和降序的操做。
排序使用了JavaScript数组的sort()
方法,这里之因此返回1
或-1
,而不直接返回a[key]<b[key]
,也就是true
或false
,是由于在部分浏览器对sort()
的处理不一样,而1
和-1
能够作到兼容。
排序前,先将全部列的排序状态都重置为normal
,而后设置当前列的排序状态(asc
或desc
),对用到render的<a>
元素的class
名称on
,后面经过CSS来高亮显示当前列的排序状态。
当渲染完表格后,父级修改了data
数据,好比增长或删除,v-table
的currentData
也应该更新,若是某列已经存在排序状态,更新后应该直接处理一次排序。
经过遍历currentColumns
来找出是否按某一列进行过排序,若是有,就按照当前排序状态对更新后的数据作一次排序操做。
<p data-height="365" data-theme-id="0" data-slug-hash="XYMmJr" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-可排序表格组件" class="codepen">See the Pen Vue-可排序表格组件 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>
发布一条留言,须要的数据有昵称和留言内容,发布操做应该在根实例app
内完成。留言列表的数据也是从app
获取。
数组list
存储了全部的留言内容,经过函数handleSend
给list
添加一项留言数据,添加成后把texrarea
文本框置空。
Render函数内的节点使用v-model
:动态绑定value
,而且监听input
事件,把输入的内容经过$emit('input')
派发给父组件。
列表数据list
为空时,渲染一个“列表为空”的信息提示节点;不为空时,每一个list-item
赢包含昵称、留言内容和回复按钮3个子节点。
this.list.forEach
至关于template
里的v-for
指令,遍历出每条留言。句柄handleReply
直接向父组件派发一个事件reply
,父组件(app
)接收后,将当前list-item
的昵称提取,并设置到v-textarea
内。
<p data-height="365" data-theme-id="0" data-slug-hash="ZRKGrR" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-留言列表" class="codepen">See the Pen Vue-留言列表 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>