IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 解决Antd输入框卡顿问题及Pubsub.js的使用 -> 正文阅读

[JavaScript知识库]解决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
  1. 简单使用
    导入
	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)
  },
  1. 记得发布了消息 要在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 style="margin-left: 10px;" @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"
          style="width: 100%;"
        />
      </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"
        style="width: 100%;"
      />
    </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"
        style="width: 100%;"
      />
    </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">
        <a-checkbox value="1" name="type3">
          Online
        </a-checkbox>
        <a-checkbox value="2" name="type3">
          Promotion
        </a-checkbox>
        <a-checkbox value="3" name="type3">
          Offline
        </a-checkbox>
      </a-checkbox-group>
    </a-form-model-item>
    <a-form-model-item label="组件三:Resource3s" prop="resource3">
      <a-radio-group v-model="form.resource3">
        <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="desc3">
      <a-input v-model="form.desc3" 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>
export default {
  name: 'FormTableOne',
  data () {
    return {
      labelCol: { span: 4 },
      wrapperCol: { span: 14 },
      other: '',
      form: {
        name3: '',
        region3: undefined,
        date3: undefined,
        delivery3: false,
        type3: [],
        resource3: '',
        desc3: ''
      },
      rules: {
        region3: [
          {
            required: true,
            message: 'Please select Activity zone',
            trigger: 'change'
          }
        ],
        date3: [
          { required: true, message: 'Please pick a date', trigger: 'change' }
        ],
        resource3: [
          {
            required: true,
            message: 'Please select activity resource3',
            trigger: 'change'
          }
        ],
        desc3: [
          {
            required: true,
            message: 'Please input activity form',
            trigger: 'blur'
          }
        ]
      }
    }
  },
  methods: {
    onSubmit () {
      return new Promise((resolve, reject) => {
        this.$refs.ruleForm.validate(valid => {
          if (valid) {
            console.log('表单3通过')
            resolve(valid)
          } else {
            console.log('error submit!!')
            reject(valid)
            return false
          }
        })
      })
    },
    resetForm () {
      this.$refs.ruleForm.resetFields()
    }
  }
}
</script>

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-03 12:57:17  更:2021-12-03 12:57:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:16:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码