1.组件封装之v-model
在vue文档中,有关于v-model的仔细说明。其中关键一点:
v-model其实是隐藏了:value 和@input 的,特别是后者,在自定义组件中,
子组件需要往外触发事件进而改变父组件的值时,尤其关键!
对于子组件来说,必须要有这个$emit !!!
2.组件封装之render函数
以下是 iview框架下,给表格加单选框的一个功能;需要用到render函数进行扩展。
那么这里,应该得到启发。我封装一个组件,我除了提供slot给外面,是否可以像这样,外面可以通过配置属性,进而传一个render函数到我的这个自定义组件中;以及,如何处理这个传进来的render函数。接下来不妨先练习一下render函数的使用,再来说如何在组件封装中使用render函数这件事。
先学习一下iview框架封装的table-header,它可以用props–>render来接收外部的一个函数。
这里是一个普通的js文件,导出了一个 {…} 对象;
在vue文件中可以导入这个 {…} 对象;并注册到当前组件中。js文件当组件用,这点是可以学习一下的。
3.js文件可以在vue项目中当组件用
export default {
name: 'xdcTest',
functional: false,
props: {},
render: (h, ctx) => {
return h('div','hello xudechuan')
}
}
4.组件封装之api式调用
如 this. m e s s a g e . x x x x , t h i s . message.xxxx,this. message.xxxx,this.prompt.xxx这种组件。
5.组件封装之–兄弟组件通信
a. 多个vue文件(4,5个甚至10来个)需要共用一套业务逻辑,那么兄弟组件通信 适合用vuex来做。
b. 一些字典查询类型的数据,需要多个子孙节点共用;那么适合用 provide/inject 来做。
c. 一些相对比较固定的组件(比如 商品卡片),适合用props传参进来,保持独立性,而不是参和vuex。
6.组件封装之–大表单拆装
/** 点击提交按钮 */
async submit() {
const formCopy = uni.$u.deepClone(this.orderForm);
this.formClone = formCopy;
// 验证1 格式
const valid1 = await this.validateFormCustom(formCopy).catch((err) => {
if (err) {
this.formClone = null
this.$refs.uToast.show({
message: err,
})
}
})
if (!valid1) return;
// 验证2 异步验证
this.btnLoading = true;
const valid2 = await this.validateProduct(formCopy).catch((err) => {
if (err) {
this.formClone = null
this.$refs.uToast.show({
message: err,
})
}
})
this.btnLoading = false;
if (!valid2) return;
/** 验证3 */
if (this.isConfirm && this.orderType != 1) {
this.btnLoading = true;
const valid3 = await this.validateMoney(formCopy).catch((err) => {
if (err) {
this.moneyShow = true
}
})
this.btnLoading = false;
if (!valid3) return;
}
/** 验证4 */
if (this.allNum > Number(this.orderForm.shipInfoDto.loadMax)) {
this.modalShow = true;
return;
}
// 最终请求
this.sendDispatch()
},
/** 验证数据格式 */
validateFormCustom(formCopy) {
return new Promise((resolve, reject) => {
/** a信息 */
const createDtoList = formCopy.createDtoList
for (var i = 0; i < createDtoList.length; i++) {
const createDto = createDtoList[i]
const wrongPro = this.wrongPro(createDto.materials)
if (!createDto.wtPurchaseOrder.ccName) reject("请选择xx");
if (!createDto.wtPurchaseOrder.terminalUse) reject('请选择xx');
if (!createDto.wtPurchaseOrder.deliveryArea) reject('请选择xx');
if (createDto.materials.length <= 0) reject('请选择xx');
if (createDto.materials.length > 10) reject('每个客户最多选择10条产品信息,请删减');
if (this.isNullPro(createDto.materials)) reject('产品信息请填写完成(数值不能为0)');
if (wrongPro) reject(`${wrongPro}比例不是100%, 请修改`);
}
/** b信息 */
const shipInfoDto = formCopy.shipInfoDto
if (!shipInfoDto.shipName) reject('请选择xx');
if (!shipInfoDto.contact) reject('请输入xx');
if (!shipInfoDto.phoneNumber) reject('请输入xx');
if (!uni.$u.test.mobile(shipInfoDto.phoneNumber)) reject('请输入正确的手机号');
if (!shipInfoDto.loadMin || !shipInfoDto.loadMax) reject('请输入xx');
/** 通过验证 */
resolve(true)
})
},
/** 验证xxx是否充足 */
validateMoney() {
return new Promise((resolve, reject) => {
const ccId = this.orderForm.createDtoList[0].ccId
const mcList = this.orderForm.createDtoList[0].materials
clientServiceGetByCcId({ccId}).then((res) => {
this.moneyObj = res
this.realMoney = (res.advanceBalance - res.debtQuota).toFixed(2)
if (allMoney > this.realMoney) {
reject("xxx不足")
} else {
resolve(true)
}
}).catch((err) => {
reject(false)
})
})
},
7.组件封装之–slot
<div class="container">
<footer>
<slot name="footer"></slot>
</footer>
</div>
<base-layout>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
注意: v-slot 后面是冒号不是等号;可用template进行包裹;
或者: slot=“reference” 这么写
8.watch
注意写法,不然不会生效
timeGap: {
handler: function (val) {
this.rectList = this.rectList.map((item, index) => {
return {
...item,
planTime: val[index],
}
})
},
deep: true,
immediate: true,
},