使用render封装一个select组件
不求人0 人气:0使用render封装一个select组件
父组件
value - {{ value }} ; value2 - {{ value2 }} <!-- disabled clearable --> <Select v-model="value" :option-data="optionData" placeholder="请选择" clearable /> <Select v-model="value2" :option-data="optionData" /> value: '', // 默认值为空字符串 value2: 'area1', optionData: [ { label: '区域1', value: 'area1' }, { label: '区域2', value: 'area2' } ],
Select.vue
<script> export default { name: 'Select', props: { value: { default: '', type: [String, Number] }, optionData: { default: () => { return [] }, type: Array } }, computed: { newValue: { get({ value }) { return value }, set(val) { this.$emit('input', val) } } }, methods: { onChangeHandle(val) { this.newValue = val } }, render(createElement) { return createElement( // 标签 'el-select', // 相关属性参数 { // html 相关的属性 placeholder id 等 attrs: { ...this.$attrs // ( { placeholder:请输入 } ) }, // props相关的 props: { value: this.newValue }, // 事件相关 on: { change: this.onChangeHandle } }, this.optionData && this.optionData.map(option => { return createElement( 'el-option', { props: { label: option.label, value: option.value } } ) }) ) } } </script>
效果
vue另类封装--render函数封装
在讲解render函数封装前,扩展一下组件自动全局注册的方法
先看看文件的结构
接下来就是注册代码(即lib下的index.js代码)
export default { install(Vue) { // 读取components文件夹下的文件 // const req = require.context('路径','是否读取子文件夹','正则匹配') // req是一个函数,该函数有三个属性分别是resolve、keys、id // 下面进行详细说明这三个属性 const req = require.context("@/components", false, /\.vue$/); //拿到读取文件的路径 //导入处理 req.keys().forEach((item) => { const com = req(item).default; // 全局注册组件 Vue.component(com.name, com); }); }, };
接下来我们在App文件直接使用components下的组件
<template> <div> <myA></myA> <myB></myB> </div> </template> <script> export default { name: "", data() { return { flag: false, }; }, computed: {}, methods: {}, }; </script> <style lang="less" scoped></style>
resolve
:它是一个函数,接收一个参数(这个参数是匹配文件的相对路径),返回值是匹配文件相对于项目的路径keys
:它也是一个函数,返回的是匹配成功文件的相对路径(不包括文件名称)id
:返回的是一个字符串,匹配的文件夹的路径()、匹配规则等
render函数封装
下面封装以面包屑为例
在a.vue下定义组件
<template> <span> <router-link v-if="to" :to="to"> <slot /> </router-link> <span v-else> <slot /> </span> </span> </template> <script> export default { name: "BreadcrumbItem", props: { to: { type: [Object, String], default: "", }, }, }; </script>
在b组件进行封装
<script> export default { name: "Breadcrumb", // 开启函数组件模式,它内部的东西不是响应式,并且没有生命周期 functional: true, render: (h, context) => { //创建数组接收虚拟节点 const vnodeArr = []; context.slots().default.forEach((item, index, arr) => { // 将处箭头外的虚拟dom存储起来 vnodeArr.push(item); // 判断是不是最后一项,是最后一项就不要加箭头 if (arr.length - 1 !== index) { // 加上箭头虚拟节点 vnodeArr.push(h("i", { class: "el-icon-arrow-right" })); } }); // render作用:它会return一个虚拟dom,return什么就渲染相应的实体Dom // h:创建虚拟DOM,有三个参数 参数一:标签/组件 参数二:虚拟dom配置 参数三:虚拟dom/子节点 // h(标签名/组件,{虚拟dom配置},子集:也是虚拟dom节点信息支持字符串与数组) // 进行渲染,h第三个参数可以为数组 return h("span", {}, vnodeArr); }, }; </script>
App组件运用
<template> <div> <Breadcrumb> <BreadcrumbItem to="/">首页</BreadcrumbItem> <BreadcrumbItem>活动列表</BreadcrumbItem> <BreadcrumbItem>活动管理</BreadcrumbItem> <BreadcrumbItem>活动详情</BreadcrumbItem> </Breadcrumb> </div> </template> <script> export default { name: "", data() { return { flag: false, }; }, computed: {}, methods: {}, }; </script> <style lang="less" scoped></style>
效果图如下
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容