函数化组件

函数化组件

Vue提供了一个functional的布尔值选项,设置为true可使组件无状态和无实例,也就是没有datathis上下文。这样用render函数返回虚拟节点能够更容易渲染,由于函数化组件只是一个函数,渲染开销要小不少。html

使用函数化组件时,Render函数提供了第二个参数context来提供临时上下文。组件须要的datapropslotschildrenparent都是经过这个上下文来传递。好比this.level要改写为context.props.levelthis.$slots.default改变为context.childrenvue

用函数化组件展现一个根据数据智能选择不一样组件的场景:数组

<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

  1. 程序化地在多个组件中选择一个。
  2. 在将childrenpropsdata传递给子组件以前操做它们。

JSX

为了让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>插件

实战:使用Render函数开发可排序的表格组件

表格组件的全部的内容(表头和行数据)由两个prop构成:columnsdata。二者都是数组,columns用来描述每列的信息,并渲染在表头<head>内,能够指定某一列是否须要排序;data时每一行的数据,由columns决定每一行里各列的顺序。

为了让排序后的columnsdata不影响原始数据,给v-table组件的data选项添加两个对应的数据,组件全部的操做将在这两个数据上完成,不对原始数据作任何处理。

columns的每一项是一个对象,其中titlekey字段是必填的,用来标识这列的表头标题,key的对应data中列内容的字段名。sortable是选填字段,若是值为true,说明该列须要排序。

v-talbe组件的prop:columnsdata的数据已经从父级传递过来,v-table不直接使用它们,而是使用data选项的currentColumnscurrentData。因此在v-table初始化时,须要把columnsdata赋值给currentColumnscurrentData。在v-tablemethods选项里定义两个方法用来复制,并在mounted钩子内调用。

map()是JavaScript数组的一个方法,根据传入的函数从新构造一个新数组。

排序分升序(asc)和降序(desc)两种,并且同时只能对一列数据进行排序,与其余列互斥,为了标识当前列的排序状态,在map列添加数据时,默认给每列都添加一个_sortType的字段,而且赋值为normal,表示默认排序(也就是不排序)。

在排序后,currentData每项的顺序可能都会发生变化,因此给currentColumnscurrentData的每一个数据都添加_index字段,表明当前数据在原始数据中的索引。

render(h) {
    var ths = [],
        trs = [];
    return h('table', [
        h('thead', [
            h('tr', ths)
        ]),
        h('tbody', trs)
    ])
}

这里的h就是createElement,只是换了个名称。

表格主题trs是一个二维数组,数据由currentColumnscurrentData组成。

先遍历全部的行,而后再每一行内再遍历各列,最终组合出主题内容节点trs

若是col.sortable没有定义,或值为false,就直接把col.title渲染出来,不然除了渲染title,还加了两个<a>元素来实现升序和降序的操做。

排序使用了JavaScript数组的sort()方法,这里之因此返回1-1,而不直接返回a[key]<b[key],也就是truefalse,是由于在部分浏览器对sort()的处理不一样,而1-1能够作到兼容。

排序前,先将全部列的排序状态都重置为normal,而后设置当前列的排序状态(ascdesc),对用到render的<a>元素的class名称on,后面经过CSS来高亮显示当前列的排序状态。

当渲染完表格后,父级修改了data数据,好比增长或删除,v-tablecurrentData也应该更新,若是某列已经存在排序状态,更新后应该直接处理一次排序。

经过遍历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存储了全部的留言内容,经过函数handleSendlist添加一项留言数据,添加成后把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>

相关文章
相关标签/搜索