修改Component函数 ,添加自定义组件基础配置
需求由来
在写自定义组件过程中,往往会有一些重复代码需要书写,如下
Component({
data: {
xxx: 'xxx',
_xxx:'_xxx',
globalData:getApp().globalData
},
options: {
addGlobalClass: true,
multipleSlots: true,
pureDataPattern:/^_/,
virtualHost: true
},
behaviors:['xxx'],
externalClasses: ['class'],
properties: {
style: String
},
lifetimes:{
attached(){
console.log(this.data.globalData)
//this.theme('bluesky') 设置主题颜色
//......
}
}
})
刚刚开始还可以通过将部分属性打包成 behaviors在需要的组件中加载,但还是有些属性可能是全局自定义组件都需要用到的,单独在每次创建自定义组件的时候加behavior还是感觉浪费时间。找了下没找到官方为Comonents函数全局注入属性的类似behavior混入配置,于是想自己写一个。
整体逻辑
建立一个函数(mixinComponent) 内部合并mixinOpt(要合并的属性对象) 和 curOpt(初始化组件页时候传入的配置对象)为一个新的options对象,再调用Component(options )。这个函数要在app.js中先调用。
分享代码
app.js
import {mixinComponent} from './utils/mixinComponent'
App({
globalData:{
test:'hello world'
}
})
// 因为我这里要加入全局globalData,所以在App之后调用了
mixinComponent({
data: {
xxx: 'xxx',
_xxx:'_xxx',
globalData:getApp().globalData
},
options: {
addGlobalClass: true,
multipleSlots: true,
pureDataPattern:/^_/,
virtualHost: true
},
externalClasses: ['class'],
properties: {
style: String
},
lifetimes:{
attached(){
console.log(this.data.globalData.test)
//this.setTheme('bluesky') 设置主题颜色
}
}
})
Component.js
Component({
data: {
name:'zhao'
},
methods: {
},
lifetimes: {
attached() {
console.log(this.data.test,this.data.globalData.test)
}
}
})
mixinComponet.js
// 定义一个混合组件函数,传入的参数类型和Component一致
export let mixinComponent = function (mixinOpt) {
//保存原始Component
let originComponent = Component;
//重新定义Component
Component = function (opt) {
//把建立Component的配置对象和混入的配置对象合并
let newOpt = mergeOpt(opt, mixinOpt);
//返回 原始Component 参数为混合完毕的新配置对象
return originComponent(newOpt);
};
//为了满足函数返回类型需要 返回String
return '';
};
function mergeLifetimes(curOptFunc, mixinLifetimesFunc, curOpt, lifetimesName) {
const temp = curOptFunc;
curOpt[lifetimesName] = function (e) {
mixinLifetimesFunc.call(this, e);
temp.call(this, e);
};
}
/**
*
* [@param](/user/param) curOpt 要混入的配置对象
* [@param](/user/param) mixinOpt 创立组件时候输入的配置对象
* [@param](/user/param) namespace 为了提示时候的命名空间
*/
function mergeOpt(curOpt, mixinOpt, namespace = '') {
//深度克隆mixinOpt是因为 他是个引用值,都在这个对象上面做混入,会冲突的。
let keys = Object.keys(mixinOpt);
namespace = namespace || 'mixinObj';
keys.forEach((propName) => {
if (!curOpt.hasOwnProperty(propName)) { //如果没有这个属性
curOpt[propName] = mixinOpt[propName]; //直接赋值过去
}
else { //有这个属性的情况下
if (propName === 'behaviors' || propName === 'externalClasses') { //这个属性是behaviors 合并
curOpt[propName] = [...new Set([...curOpt[propName], ...mixinOpt[propName]])];
}
else if (propName === 'lifetimes') { //这个属性是lifetimes 合并
var lifenameArr = Object.keys(mixinOpt.lifetimes); //要合并的生命周期函数
lifenameArr.forEach(ele => {
if (!curOpt.lifetimes[ele]) { //如果原来没有,直接赋值过去,
curOpt.lifetimes[ele] = mixinOpt.lifetimes[ele];
}
else { //如果原来有 合并在一起
mergeLifetimes(curOpt.lifetimes[ele], mixinOpt.lifetimes[ele], curOpt.lifetimes, ele);
}
});
}
else if (typeof mixinOpt[propName] !== 'object' || propName === 'pureDataPattern') { //如果不是对象
throw Error(`${namespace}中有${propName}这个属性了`);
}
else { //这个属性是对象 递归
curOpt[propName] = mergeOpt(curOpt[propName], mixinOpt[propName], namespace + '.' + propName);
}
}
});
return curOpt;
}
总结
- 当自定义组件的配置文件中与mixinOpt冲突的时候会提示报错
- 因为我是用ts写的,mixinOpt的类型检查会在输入错误属性类型提前报错,上面是编译为js后的代码,需要注意mixinOpt中输入无效字段可能出现未知错误。
- 配置合并中可能有未判断的字段,或者后续官方增加的配置也要加入进去。
- 如果您看错哪里写的问题,请浏览回复。
- 如果文章对您有所帮助,请点赞,后续会多多发帖。