当前位置: 首页 > Web前端 > HTML

你不知道但在Vue中非常实用的黑科技

时间:2023-04-02 12:01:15 HTML

最近几个月一直致力于iView的开源工作,完成了大大小小30多个UI组件,积累了很多经验Vue组件开发。还有很多有花样和黑科技的组件。其中一些功能在Vue文档中提到但很容易被忽略,还有一些没有写在文档中。今天就来说说Vue组件的进阶玩法。本文所写的大部分内容都用在了iView项目中。大家可以关注一下,结合源码研究其中的奥秘。项目地址:https://github.com/iview/iview目录递归组件自定义组件使用v-model使用$compile()在指定上下文中手动编译组件内联模板inline-template隐式创建Vue实例递归组件recursive组件是文档中介绍,只要为组件指定一个name字段,就可以在组件中递归调用自己,例如:variview=Vue.extend({name:'iview',template:'

'+//递归调用自己''+'
'})这种用法在业务中不常见,在iView的级联选择组件中使用了这个特性(https://github.com/iview/iview/tree/master/src/components/cascader)如下图所示:图中每一列都是一个组件(caspanel.vue),一开始我想到的是用v-for来渲染list,但是后来发现可扩展性极低,而且随着功能的丰富,实现难度大,处理逻辑多,所以改写成递归组件:propsprops有很多,可以忽略,但关键的两个是data和sublist,即当前列数据和子集数据,因为事先不知道他们有多少下属,所以只需要将下属数据传递给组件本身即可。如果为空,则递归结束。Vue的设计真的很精妙。注意:Vue1.x和2.x都支持该方法。自定义组件使用v-model我们知道v-model是用来对表单元素进行双向绑定的,比如:此时数据双向绑定,输入的内容会真实显示在页面上时间。在Vue1.x中,自定义组件可以使用props的.sync双向绑定,例如:在Vue2.x中,可以直接在自定义组件上使用v-model,例如:在组件my-component中,可以通过this.$emit('input')的数据的值已更改。虽然这在Vue1.x中不能使用,但是如果你的组件模板外层是input、select、textarea等支持绑定v-model特性的元素,也是可以使用的。比如my-component的代码是:也可以使用上面2.x的写法。使用$compile()在指定上下文中手动编译组件。注意:该方法是在Vue1.x中介绍使用。官方文档没有对这种方法给出任何说明。不要过分依赖这种方法。使用$compile()方法,可以在任意指定上下文(Vue实例)手动编译组件,iView新发布的表格组件Table中使用:https://github.com/iview/iview/tree/master/src/components/table/cell.vue由于table的column配置是通过一个Object传给props的,所以不能像slot一样用Vue代码自动编译这部分,因为传入的都是字符串,比如:{render(row){return`${row.name}`}}render函数最后返回一个字符串,里面包含一个自定义组件i-button,如果直接使用{{{}}}表示i-button不会被编译,所以为了支持在cell中渲染自定义组件,使用了$compile()方法。例如,我们在组件的父级别编译://代码片段consttemplate=this.render(this.row);//通过上面的渲染函数获取字符串constdiv=document.createElement('div');div.innerHTML=template;this.$parent.$compile(div);//在父上下文中编译组件this.$el.appendChild(cell);//将编译后的html插入到当前组件中,以便编译i-button。在某些时候使用$compile()确实可以带来好处,但是也有很多值得思考的问题:这种编译容易混淆作用域,所以你需要知道它是在哪个Vue实例上编译的;手动编译后,还需要在适当的时候使用$destroy()手动销毁;有时候容易重复编译,所以记得保存当前编译实例的id,可以通过Vue组件的_uid唯一标识(每个Vue实例都会有一个自增id,可以通过this._uid获取)另外,Vue1.x文档中还提到了另外一个$mount()方法,也可以实现类似的效果。在Vue2.x的文档中,有Vue.compile()方法,用于在render函数中编译模板字符串,读者可以一起看看。内联模板inline-template内联模板并不是什么新鲜事,在文档中也有说明,只是平时很少用到,所以很容易被忽略。简单的解释就是用组件的slot作为这个组件的模板,更加灵活:{{data}}因为使用了inline-template内联模板,子组件不需要