Skip to content

popEitor和dialogbox组件相关问题解答

ajaxzheng edited this page May 31, 2023 · 2 revisions

1. popEditor 数据请求触发机制

预期效果:配置数据请求函数,点击输入框后面的【...】才发出远程请求

现状:当渲染此组件时,就触发数据请求。这样,当配置了多个popEditor,页面渲染时会一次性发出大量的远程数据请求,从而影响到界面展示速度,也给服务器带来压力(用户只有少数访问使用popEditor 组件,那么每次从远程请求返回的大量数据资源相当于浪费了)。

解决方案:

配置auto-lookup为false,设置初始化不请求数据,也可以调用this.$refs.popeditor.handleSearch()主动调用请求方法,具体案例如下:

<template>
  <tiny-popeditor
    multi
    :remote-search="remoteSearch"
    v-model="value"
    show-pager
    :grid-op="gridOp"
    text-field="name"
    :auto-lookup="false"
    value-field="id"
    ref="popeditor"
    :conditions="conditions"
    @click="foucus"
  ></tiny-popeditor>
</template>

<script>
import { Popeditor } from '@opentiny/vue'

export default {
  components: {
    TinyPopeditor: Popeditor
  },
  data() {
    return {
      value: 5,
      gridOp: {
        columns: [
          {
            field: 'id',
            title: 'ID',
            width: 40
          },
          {
            field: 'name',
            title: '名称'
          },
          {
            field: 'city',
            title: '城市',
            width: 80
          },
          {
            field: 'employees',
            title: '员工',
            width: 80
          }
        ],
        data: [],
        pagerOp: {
          pageSizes: [5, 10, 15]
        }
      },
      conditions: [
        { label: '公司名', field: 'name' },
        { label: '城市', field: 'city' }
      ]
    }
  },
  methods: {
    foucus(){
    const pop=this.$refs.popeditor
    // 主动调用请求方法
    pop.handleSearch()
    },
    remoteSearch({ page }) {
      const randomAlphabets = () => {
        return Array.from({ length: 5 })
          .map(() => String.fromCharCode(65 + Math.floor(26 * Math.random())))
          .join('')
      }
      const { currentPage, pageSize } = page
      const data = Array.from({ length: page.pageSize }).map((item, i) => {
        return {
          id: pageSize * (currentPage - 1) + i + 1,
          name: randomAlphabets() + 'YX公司',
          city: ['福州', '深圳', '中山', '龙岩', '韶关', '黄冈', '赤壁', '厦门'][Math.floor(Math.random() * 8)],
          employees: Math.ceil(Math.random() * 10000)
        }
      })
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({ data, total: 200 })
        }, 500)
      })
    }
  }
}
</script>

2. popEditor 联动机制

场景需求:表单里popEditor 需要实现多级联动,需实现数据的懒加载。

比如:表单有公司、部门两项,都是popEditor 组件,而【部门】项的远程数据源需要依赖【公司】项的选中值,从而返回对应数据。按照问题一的现状,页面完成渲染后,用户还没选择【公司】项,【部门】项的远程数据就请求回来了,不符合使用需求。

解决方案:通过属性auto-lookup,和popeditor相关方法去实现,通过控制台打印:this.$refs.popeditor,可以查看很多实用方法

3. 诸如popEditor、dialogBox、modal 组件的渲染机制

目前问题:当visible 设为false,页面渲染完成后,只是把对应的DOM 设为display:false,不能实现组件的重新生成实例。

解决方案:可以通过在dialogbox、modal框内部第一层div设置v-if值来解决,案例如下:

<template>
  <div>
    <tiny-button @click="boxVisibility = true">弹出表单</tiny-button>
    <tiny-dialog-box :visible="boxVisibility" @update:visible="boxVisibility = $event" title="消息" width="30%" :is-form-reset="false">
      <div v-if="boxVisibility">
        <tiny-form :model="formData" label-width="100px" label-position="top">
        <tiny-form-item label="人员姓名" prop="name">
          <tiny-input type="text" v-model="formData.name"></tiny-input>
        </tiny-form-item>
        <tiny-form-item label="岗位" prop="type">
          <tiny-radio-group v-model="formData.type">
            <tiny-radio :label="0">研发</tiny-radio>
            <tiny-radio :label="1">非研发</tiny-radio>
          </tiny-radio-group>
        </tiny-form-item>
        <tiny-form-item label="特长" prop="goodAt">
          <tiny-checkbox :indeterminate="isIndeterminate" v-model="checkAll">全部</tiny-checkbox>
          <tiny-checkbox-group v-model="formData.goodAt">
            <tiny-checkbox v-for="(goodAtItem, index) in goodAtOptions[formData.type]" :label="goodAtItem" :key="goodAtItem + index">{{
              goodAtItem
            }}</tiny-checkbox>
          </tiny-checkbox-group>
        </tiny-form-item>
      </tiny-form>
      </div>
      <template #footer>
        <tiny-button type="primary" :loading="btnSubmit.loading" @click="handleSubmit">{{ btnSubmit.text[btnSubmit.loading] }}</tiny-button>
      </template>
    </tiny-dialog-box>
  </div>
</template>

<script lang="jsx">
import { Button, DialogBox, Form, FormItem, Input, Radio, RadioGroup, Checkbox, CheckboxGroup } from '@opentiny/vue'
import Notify from '@opentiny/vue-notify'

export default {
  components: {
    TinyButton: Button,
    TinyDialogBox: DialogBox,
    TinyForm: Form,
    TinyFormItem: FormItem,
    TinyInput: Input,
    TinyRadio: Radio,
    TinyRadioGroup: RadioGroup,
    TinyCheckbox: Checkbox,
    TinyCheckboxGroup: CheckboxGroup
  },
  data() {
    return {
      btnSubmit: {
        loading: false,
        text: {
          true: '提交中',
          false: '确定'
        }
      },
      boxVisibility: false,
      formData: {
        name: '',
        type: 0,
        goodAt: []
      },
      goodAtOptions: [
        ['架构', '算法', '自动化'],
        ['UI设计', 'EXCEL', 'PPT制作']
      ]
    }
  },
  methods: {
    handleSubmit() {
      this.btnSubmit.loading = true
      this.mockPost().then((response) => {
        if (response.status === 200) {
          this.btnSubmit.loading = false
          this.boxVisibility = false
          Notify({
            title: '成功',
            message: '表单已成功提交!',
            offset: 0
          })
        }
      })
    },
    mockPost() {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({ status: 200 })
        }, 800)
      })
    },
    resetForm() {
      this.formData = {
        name: '',
        type: 0,
        goodAt: []
      }
    }
  },
  computed: {
    checkAll: {
      get() {
        return this.formData.goodAt.length === this.goodAtOptions[this.formData.type].length
      },
      set(val) {
        this.formData.goodAt = val ? [...this.goodAtOptions[this.formData.type]] : []
      }
    },
    isIndeterminate: {
      get() {
        return this.formData.goodAt.length > 0 && this.formData.goodAt.length < this.goodAtOptions[this.formData.type].length
      }
    }
  }
}
</script>
Clone this wiki locally