目录
Mixin【混入】
缺陷
HOC(higher order component)【高阶组件】
相比较Mixin的优点:
不足:
Renderless组件【函数式组件,无渲染组件,Vue社区使用比较多的一种业务复用模式】
优点:
- Mixins:混入 (mixins): 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
- HOC(higher order component)【高阶组件】:高阶组件(HOC)是React中用于复用组件逻辑的一种高级技巧。HOC自身并不是React API的一部分,它是一种基于React的组合特性而形成的设计模式。高阶组件听起来挺唬人的,只看名字恐怕不是那么容易明白究竟是何物,而且通常来讲高阶组件并不是组件,而是接受组件作为参数,并且返回组件的函数。
- Renderless组件:函数式组件,无渲染组件
Mixin【混入】
<template>
<div>
<input type="text" @blur="blur" />
{{ errmsg }}
</div>
</template>
<script>
import validateMixin from "./mixin";
export default {
mixins: [validateMixin],// 之影响这一个页面,单个页面混入
data: () => ({ errmsg: "" }),
methods: {
blur() {
this.validate();
}
}
}
</scrpit>
validateMixin
export default {
methods: {
validate() {
/**
* 校验逻辑
*/
return true;
}
}
}
- 同名钩子函数将合并为一个数组,混入对象的钩子将在组件自身钩子之前调用。
- 二者的methods、components和directives【自定义指令】,将被合并为同一个对象。若对象键名冲突时,取组件对象的键值对(mixin里面的同名【键名】会丢失)
缺陷
- 打破了原有组件的封装
- 增加组件复杂度
- 可能会出现命名冲突的问题
- 仅仅只是对逻辑的复用,模板不能复用(假如什么示例中errmsg由minxin中的validate返回,那就需要在每个用到的页面写模板)
HOC(higher order component)【高阶组件】
高阶函数的应用,装饰者模式的一种实现
HOC:函数接收一个组件作为参数,并返回一个新组件;可复用的逻辑在函数中实现
App.vue文件
<template>
<div id="app">
<img width="25%" src="./assets/logo.png">
<validate-input :rules="rules"/>
</div>
</template>
<script>
import CustomInput from "./components/CustomInput";
import ValidateHoc from "./components/hoc.js";
const ValidateInput = ValidateHoc(CustomInput);
export default {
name: "App",
data() {
return {
rules: [
{
test: function(value) {
return /\d+/.test(value);
},
message: "请输入一个数字"
}
]
};
},
components: {
ValidateInput
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
CustomInput.vue文件
<template>
<input type="text" @blur="$emit('blur', value)" v-model="value">
</template>
<script>
export default {
props: ["initValue"],
data() {
return {
value: this.initValue
};
}
};
</script>
hoc.js文件
const ValidateHoc = Component => ({
name: `hoc-${Component.name}`,
props: ["rules"],
data() {
return {
errMsg: "",
value: ""
};
},
methods: {
validate(value) {
this.value = value;
let validate = this.rules.reduce((pre, cur) => {
let check = cur && cur.test && cur.test(this.value);
this.errMsg = check ? "" : cur.message;
return pre && check;
}, true);
return validate;
}
},
render() {
console.log(this.value);
return (
<div>
<Component on-blur={this.validate} initValue={this.value} />
{this.errMsg || ""}
</div>
);
}
});
export default ValidateHoc;
相比较Mixin的优点:
- 模板可复用
- 不会出现命名冲突(本质上是HOC是套了一层父组件)
不足:
- 组件复杂度高,多层嵌套,调试会很痛苦
Renderless组件【函数式组件,无渲染组件,Vue社区使用比较多的一种业务复用模式】
- 复用的逻辑沉淀在包含slot插槽的组件
- 接口由插槽Prop来暴露
左面子组件,右面是复用逻辑
SBody.vue文件【子组件】
<template>
<div>
// 暴露出插槽Prop方法【validate】
<s-validate #default="{ validate }" :value="value" :rules="rules">
// 调用暴露出插槽Prop方法【validate】
<input type="text" @blur="validate" v-model="value" />
</s-validate>
<s-validate #default="{ validate }" :value="text" :rules="textRules">
<textarea type="text" @blur="validate" v-model="text" />
</s-validate>
</div>
</template>
<script>
import SValidate from "./SValidate";
export default {
data: () => ({
value: "hi",
text: "hi",
rules: [
{
test: function(value) {
return /\d+/.test(value);
},
message: "请输入一个数字"
}
],
textRules: [
{
test: function(value) {
return value;
},
message: "请输入一个非空的值"
}
]
}),
components: {
SValidate
}
};
</script>
SValidate.vue【复用逻辑】
<template>
<div>
<slot :validate="validate"></slot>
{{ errMsg }}
</div>
</template>
<script>
export default {
props: ["value", "rules"],
data() {
return { errMsg: "" };
},
methods: {
validate() {
let validate = this.rules.reduce((pre, cur) => {
let check = cur && cur.test && cur.test(this.value);
this.errMsg = check ? "" : cur.message;
return pre && check;
}, true);
return validate;
}
}
};
</script>
优点:
- 模板可复用
- 不会出现命名冲突
- 符合依赖倒置原则
- 复用的接口来源清晰