更好的封装vue组件
我给组件分类
-
单向组件
组件只关心数据的展示和事件挂载;单纯的数据展示组件。
-
双向组件
响应式组件,组件除了展示父组件传入数据的之外,在组件中可能会有点击,输入等操作筛选期望数据返回给父组件。
-
API组件
适合单独的API调用方式调用,如提示框、弹出框之类的
-
高阶组件
组件嵌套超过两次
单向组件
-
场景一:仅仅用作展示
比较简单,利用vue的props特性即可;有需要的情况下可以利用computed计算属性对prop的值进行转化展示。
-
场景二:初始化展示,即可能会变动但不改动数据源
prop的值用作初始化,应该定义子组件的data属性并将prop作为其初始值。
-
场景三:""跨多代"的数据传递
利用v$attrs特性
-
高级别的组件时非常有用
-
uniapp不支持
-
包括了
class和style除外的所有属性 -
Vue会将组件被传入但未声明的Prop当做Html属性绑定到根元素上;
解决:设置inheritAttrs 为 false,
-
// 父组件
<template>
<chlid :data1="'1223'" :data2="'1232'" />
</template>
//子组件chlid
<template>
<view>
<view>这是child组件</view>
<view>{{$attrs.data1}}</view>
<view>{{$attrs.data2}}</view>
<Sun v-bind="$attrs" />
</view>
</template>
//孙组件Sun
<template>
<view>
<view >这是Sun组件{{$attrs.data1}}</view>
</view>
</template>
<script>
export default {
inheritAttrs: false,
}
</script>
双向组件
- 场景一:表单输入类型不满足需求,自定义表单输入、表单选择
v-model做了两件事:
- 将value属性值与变量值绑定(等价于:
),并将value作为返回值抛出input事件(等价于:this.$emit('input',value))- 将input事件的返回值重新赋予变量(等价于:<div :value="variable" @input="(value)=>{ this.variable = value }" />)
API组件
-
场景一:使用频繁,风格规范统一
本质上是将实例化方法挂载到vue的原型上,调用时执行实例化方法,将组件append到body当中,完成组件的渲染。
// alert.js import vue from "vue'; import alertTips from ' . /alertTips .vue'; const TipsConstructor = vue.extend(alertTips); //使用这个方法调用alertTips组件 function showTips(options) { options = options || {}; // 简单的参数处理 if( typeof options==="object" ){ options = { text: options.text,//提示文字 }else{ new Error('传参格式不对") } //实例化子组件,然后获取到DOM结构并挂载到body上 const tipsInstence = new TipsConstructor({data: options}); let timer; tipsInstence .vm = tipsInstence .$mount(): //将实例化后的组件通过appendchild方法挂载到页面上 document .getElementById( "app").appendChild(tipsInstence.vm.$el); timer = setTimeout(function(){ //1500毫秒后通过removeChild方法将组件移除 document .getElementById( 'app').removechild(tipsInstence vm.$el); clearTimeout(timer); },1500) } export default showTips;使用
import alert from './alert.js' // 挂载到Vue原型上 Vue.prototype.$Alert = alert // 然后在组件中使用 this.$Alert.showTips({text: '提示'})
高阶组件
- 场景一:假设最外层是父组件,抽屉组件为子组件,抽屉内容为孙组件。现在我们要新增一个父组件,父组件的抽屉内容是表单或者是其他全新的内容,抽屉组件保持不变。如何封装这个抽屉?
利用渲染函数,让子组件渲染自定义的内容(孙组件),而自定义的内容由父组件传入。
父组件调用抽屉
// 部分代码
<template>
<AgDrawer
:visible.sync="agDrawerData.visible" // 是否显示抽屉
:drawer="agDrawerData" // 抽屉的内容
@onDrawerAction="onAgDrawerAction" // 处理抽屉事件
/>
</template>
<script>
import DecorationOrderForm from "@/pages/DecorationOrderForm";
export default {
data(){
return {
agDrawerData: {
action: 'test',
component: DecorationOrderForm,
preload: {title: '编辑'},
drawerStyle: {
drawerClass: 'ag-drawer-mid-class'
}
}
}
}
</script>
抽屉传递数据,处理抽屉的其他逻辑
// 部分代码
<template>
<el-drawer
:visible.sync="inVisible"
:show-close="drawerStyle.showClose"
:append-to-body="drawerStyle.appendToBody"
:close-on-press-escape="drawerStyle.closeOnPressEscape"
:close-on-click-moda="drawerStyle.closeOnClickModal"
:withHeader="false"
:custom-class="drawerStyle.drawerClass"
:direction="drawerStyle.direction">
<ag-drawer-body @onDrawerClose="onDrawerClose" @onDrawerAction="onDrawerAction" v-if="inVisible"
:drawer="drawer"></ag-drawer-body>
</el-drawer>
</template>
孙组件渲染内容
<script>
export default {
name: 'AgDrawerBody',
props: {
drawer: {type: Object, default:{}},
},
render(createElement) {
if (this.drawer.component){
return createElement(this.drawer.component,{
props:{
drawer:this.drawer
},
})
}
return createElement('h1',`action:${this.action}未设置drawer`)
},
created() {
}
}
</script>
最后一句
这是沉曦的学习心得!若有不正,还望斧正。希望掘友们不要吝啬对我的建议哦,回见。