这篇文章主要介绍“Antd输入框卡顿及Pubsub.js使用问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Antd输入框卡顿及Pubsub.js使用问题怎么解决”文章能帮助大家解决问题。
项目场景
项目中通过表单来填写校验大量复杂数据
问题描述
项目中使用的是Ant Design of Vue这个组件库,使用FormModel 表单,数据字段和校验较多时,表单操作卡顿;eg: a-input输入框,等你输入完字及,几秒后才慢慢出现你输入的字符
原因分析
vue在进行输入时,进行了多次的render刷新渲染操作,导致了input框输入时发生的卡顿现象
解决方案
官方给出的解决办法,将 Form 相关的业务独立到一个单独的组件中,减少组件渲染的消耗,如果有很多校验项,可把它们分别放在不同的Form中处理
eg :
一、组件封装
将大表单拆分成三个组件表单,数据校验等操作在其组件内部实现
二、formTable中的字段有部分与formTableTwo联动
这里使用PubSub.js进行兄弟组件传值
PubSub.js的使用
1.首先安装pubsub-js
npm install --save pubsub-js
2.简单使用
导入
import PubSub from 'pubsub-js'
发送消息:
PubSub.publish(名称,参数)
订阅消息:
PubSub.subscrib(名称,函数)
取消订阅:
PubSub.unsubscrib(名称)
在formTableTwo中使用PubSub.publish(名称,参数)发送信息,formTableOne中使用PubSub.subscrib(名称,函数)接收信息。
注意:
1.PubSub.subscrib(名称,函数)接收信息的所传名称要与
PubSub.publish(名称,参数)发送信息的名称一致
2.PubSub.subscrib(名称,函数)接收信息可能会被触发多次,可以在
PubSub.subscrib(名称,函数)前使用
PubSub.unsubscribe可以解决
created () { // console.log('form1', this.form) // 解决PubSub多次调用 PubSub.unsubscribe('send'); // 订阅消息(接收消息) PubSub.subscribe('send', (name, value) => { console.log('name', name) console.log('value', value) }) // 订阅组件二的消息 PubSub.subscribe('sendTwo', (name, val) => { console.log('sendTwo', name) console.log('我是接受到的值', val) this.isShow = val }) console.log('this.form', this.form) },
3.记得发布了消息 要在vue
beforedestory中销毁取消订阅 ,发布的次数多了,会造成订阅一次触发多次的情况;
beforeDestroy () { PubSub.unsubscribe('send') PubSub.unsubscribe('sendTwo') }
三、使用Promise.all提交校验表单
子组件
onSubmit () { return new Promise((resolve, reject) => { this.$refs.ruleForm.validate(valid => { if (valid) { console.log('表单1通过') this.outgoingInfo() resolve(valid) } else { console.log('error submit!!') reject(valid) return false } }) }) },
父组件
// 表单校验 submitForm () { console.log('this.$refs.FormTableOne.form', this.$refs.FormTableOne.form) const rules1 = this.$refs.FormTableOne.onSubmit() const rules2 = this.$refs.FormTableTwo.onSubmit() const rules3 = this.$refs.FormTableThree.onSubmit() Promise.all([rules1,rules2, rules3]).then(() => { console.log('校验通过') }) },
完整demo
formGroup
<template> <div> <div> <FormTableOne ref="FormTableOne" :formInfo="form" @outgoingInfo="outgoingInfo"/> <FormTableTwo ref="FormTableTwo" /> <FormTableThree ref="FormTableThree" /> </div> <a-button type="primary" @click="submitForm"> submit </a-button> <a-button @click="resetForm"> Reset </a-button> </div> </template> <script> import FormTableOne from './components/formTableOne' import FormTableTwo from './components/formTableTwo' import FormTableThree from './components/formTableThree' import PubSub from 'pubsub-js' export default { components: { FormTableOne, FormTableTwo, FormTableThree }, data () { return { form: {} } }, created() { this.sendMessages() setTimeout(() => { this.form = { name1: '123456', region1: undefined, date1: undefined, delivery1: false, type1: [], resource1: '123', desc1: '123', name2: '', region2: undefined, date2: undefined, delivery2: false, type2: [], resource2: '', desc2: '', name3: '', region3: undefined, date3: undefined, delivery3: false, type3: [], resource3: '', desc3: '' } }, 2000) }, methods: { // 表单校验 submitForm () { console.log('this.$refs.FormTableOne.form', this.$refs.FormTableOne.form) const rules1 = this.$refs.FormTableOne.onSubmit() const rules2 = this.$refs.FormTableTwo.onSubmit() const rules3 = this.$refs.FormTableThree.onSubmit() Promise.all([rules1,rules2, rules3]).then(() => { console.log('校验通过') }) }, outgoingInfo (val) { console.log('组件一传出的值', val) Object.assign(this.form, val) console.log('主组件的值', this.form) }, resetForm () { this.sendMessages() this.form = { name1: '', region1: undefined, date1: undefined, delivery1: false, type1: [], resource1: '', desc1: '', name2: '', region2: undefined, date2: undefined, delivery2: false, type2: [], resource2: '', desc2: '', name3: '', region3: undefined, date3: undefined, delivery3: false, type3: [], resource3: '', desc3: '' } console.log('this.form', this.form) }, sendMessages () { console.log('发送') PubSub.publish('send', { name: '张三', age: 18 }) } } } </script> <style></style>
formTableOne
<template> <div> <a-form-model ref="ruleForm" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol" > <a-form-model-item ref="name1" label="组件一: name" prop="name1" v-if="isShow"> <a-input v-model="form.name1" @blur=" () => { $refs.name1.onFieldBlur() } " /> </a-form-model-item> <a-form-model-item label="组件一: zone" prop="region1"> <a-select v-model="form.region1" placeholder="please select your zone"> <a-select-option value="shanghai"> Zone one </a-select-option> <a-select-option value="beijing"> Zone two </a-select-option> </a-select> </a-form-model-item> <a-form-model-item label="组件一: time" required prop="date1"> <a-date-picker v-model="form.date1" show-time type="date" placeholder="Pick a date" /> </a-form-model-item> <a-form-model-item label="组件一: delivery1" prop="delivery1"> <a-switch v-model="form.delivery1" /> </a-form-model-item> <a-form-model-item label="组件一: type1" prop="type1"> <a-checkbox-group v-model="form.type1"> <a-checkbox value="1" name="type1"> Online </a-checkbox> <a-checkbox value="2" name="type1"> Promotion </a-checkbox> <a-checkbox value="3" name="type1"> Offline </a-checkbox> </a-checkbox-group> </a-form-model-item> <a-form-model-item label="组件一:Resource1s" prop="resource1"> <a-radio-group v-model="form.resource1"> <a-radio value="1"> Sponsor </a-radio> <a-radio value="2"> Venue </a-radio> </a-radio-group> </a-form-model-item> <a-form-model-item label="组件一: form" prop="desc1"> <a-input v-model="form.desc1" type="textarea" /> </a-form-model-item> <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }"> </a-form-model-item> </a-form-model> <a-button type="primary" @click="outgoingInfo"> Create </a-button> </div> </template> <script> import PubSub from 'pubsub-js' const list = [ '', 'name1', 'region1', 'date1', 'delivery1', 'type1', 'resource1', 'desc1' ] export default { name: 'FormTableOne', props: { formInfo: { type: Object, default: () => { return { name1: '', region1: undefined, date1: undefined, delivery1: false, type1: [], resource1: '', desc1: '' } } } }, created () { // console.log('form1', this.form) // 解决PubSub多次调用 PubSub.unsubscribe('send'); // 订阅消息(接收消息) PubSub.subscribe('send', (name, value) => { console.log('name', name) console.log('value', value) }) // 订阅组件二的消息 PubSub.subscribe('sendTwo', (name, val) => { console.log('sendTwo', name) console.log('我是接受到的值', val) this.isShow = val }) console.log('this.form', this.form) }, data () { return { isShow: true, labelCol: { span: 4 }, wrapperCol: { span: 14 }, other: '', form: { name1: '', region1: undefined, date1: undefined, delivery1: false, type1: [], resource1: '', desc1: '' }, rules: { region1: [ { required: true, message: 'Please select Activity zone', trigger: 'change' } ], date1: [ { required: true, message: 'Please pick a date', trigger: 'change' } ], resource1: [ { required: true, message: 'Please select activity resource1', trigger: 'change' } ], desc1: [ { required: true, message: 'Please input activity form', trigger: 'blur' } ] } } }, watch: { // 过滤一些不属于这个组件属性 formInfo () { let obj = JSON.parse(JSON.stringify(this.formInfo, (key, value) => { if (list.includes(key)) { return value } else { return undefined } })) this.form = Object.assign(this.form, obj) }, deep: true }, computed: { }, methods: { onSubmit () { return new Promise((resolve, reject) => { this.$refs.ruleForm.validate(valid => { if (valid) { console.log('表单1通过') this.outgoingInfo() resolve(valid) } else { console.log('error submit!!') reject(valid) return false } }) }) }, resetForm () { this.$refs.ruleForm.resetFields() }, // 将组件的值传出去 outgoingInfo () { this.$emit('outgoingInfo', this.form) } }, beforeDestroy () { PubSub.unsubscribe('send') PubSub.unsubscribe('sendTwo') } } </script>
formTabeTwo
<template> <a-form-model ref="ruleForm" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol" > <a-form-model-item ref="name2" label="组件二: name" prop="name2"> <a-input v-model="form.name2" @blur=" () => { $refs.name2.onFieldBlur() } " /> </a-form-model-item> <a-form-model-item label="组件二: zone" prop="region2"> <a-select v-model="form.region2" placeholder="please select your zone"> <a-select-option value="shanghai"> Zone one </a-select-option> <a-select-option value="beijing"> Zone two </a-select-option> </a-select> </a-form-model-item> <a-form-model-item label="组件二: time" required prop="date2"> <a-date-picker v-model="form.date2" show-time type="date" placeholder="Pick a date" /> </a-form-model-item> <a-form-model-item label="组件二: delivery2" prop="delivery2"> <a-switch v-model="form.delivery2" @change="checkChange"/> </a-form-model-item> <a-form-model-item label="组件二: type2" prop="type2"> <a-checkbox-group v-model="form.type"> <a-checkbox value="1" name="type2"> Online </a-checkbox> <a-checkbox value="2" name="type2"> Promotion </a-checkbox> <a-checkbox value="3" name="type2"> Offline </a-checkbox> </a-checkbox-group> </a-form-model-item> <a-form-model-item label="组件二:resource2s" prop="resource2"> <a-radio-group v-model="form.resource2"> <a-radio value="1"> Sponsor </a-radio> <a-radio value="2"> Venue </a-radio> </a-radio-group> </a-form-model-item> <a-form-model-item label="组件二: form" prop="desc2"> <a-input v-model="form.desc2" type="textarea" /> </a-form-model-item> <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }"> </a-form-model-item> </a-form-model> </template> <script> import PubSub from 'pubsub-js' export default { name: 'FormTableOne', data () { return { labelCol: { span: 4 }, wrapperCol: { span: 14 }, other: '', form: { name2: '', region2: undefined, date2: undefined, delivery2: false, type2: [], resource2: '', desc2: '' }, rules: { region2: [ { required: true, message: 'Please select Activity zone', trigger: 'change' } ], date2: [ { required: true, message: 'Please pick a date', trigger: 'change' } ], resource2: [ { required: true, message: 'Please select activity resource2', trigger: 'change' } ], desc2: [ { required: true, message: 'Please input activity form', trigger: 'blur' } ] } } }, created() { }, methods: { onSubmit () { return new Promise((resolve, reject) => { this.$refs.ruleForm.validate(valid => { if (valid) { console.log('表单2通过') resolve(valid) } else { console.log('error submit!!') reject(valid) return false } }) }) }, checkChange() { // 发布消息 PubSub.publish('sendTwo', false) }, resetForm () { this.$refs.ruleForm.resetFields() } } } </script>
formTableThree
<template> <a-form-model ref="ruleForm" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol" > <a-form-model-item ref="name3" label="组件三: name3" prop="name3"> <a-input v-model="form.name3" @blur=" () => { $refs.name3.onFieldBlur() } " /> </a-form-model-item> <a-form-model-item label="组件三: zone" prop="region3"> <a-select v-model="form.region3" placeholder="please select your zone"> <a-select-option value="shanghai"> Zone one </a-select-option> <a-select-option value="beijing"> Zone two </a-select-option> </a-select> </a-form-model-item> <a-form-model-item label="组件三: time" required prop="date3"> <a-date-picker v-model="form.date3" show-time type="date" placeholder="Pick a date" /> </a-form-model-item> <a-form-model-item label="组件三: delivery3" prop="delivery3"> <a-switch v-model="form.delivery3" /> </a-form-model-item> <a-form-model-item label="组件三: type3" prop="type3"> <a-checkbox-group v-model="form.type"> &nbs