«

Antd输入框卡顿及Pubsub.js使用问题怎么解决

时间:2024-6-3 12:52     作者:韩俊     分类: Javascript


这篇文章主要介绍“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

    标签: javascript

    热门推荐