学习笔记:函数化组件函数化组件Vue提供了一个functional的布尔值选项,设置为true可以使组件无状态和无实例,也就是没有data和this上下文。这样用render函数返回虚拟节点可以更容易渲染,因为函数化组件只是一个函数,渲染开销要小很多。使用函数化组件时,Render函数提供了第二个参数context来提供临时上下文。组件需要的data、prop、slots、children、parent都是通过这个上下文来传递。比如this.level要改写为context.props.level,this.$slots.default改变为context.children。用函数化组件展示一个根据数据智能选择不同组件的场景:<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>函数化组件主要适用于以下两个场景:程序化地在多个组件中选择一个。在将children、props、data传递给子组件之前操作它们。JSX为了让Render函数更好地书写和阅读,Vue提供了插件babel-plugin-transform-vue-jsx来支持JSX语法。使用createElement时,常用配置:<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写法:<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构成: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>