前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最佳实践:vue弹窗及滑块响应式

最佳实践:vue弹窗及滑块响应式

作者头像
奋飛
发布2021-08-30 10:14:49
4160
发布2021-08-30 10:14:49
举报
文章被收录于专栏:Super 前端Super 前端

下述为项目中弹窗/滑块统一处理方式汇总(下述已 el-dialog 为例

演示环境:https://eugvd.csb.app/ Demo 地址:https://codesandbox.io/s/thirsty-sun-eugvd?file=/src/components/User.vue:2122-2497

DOM 结构

方式1. (推荐1:直接注入数据「详情」) el-dialog 壳子在外,内容单独组件,后续组件可以替换为其他壳子

代码语言:javascript
复制
<template>
  <el-dialog
    title="编辑"
    :visible.sync="centerDialogVisible"
    width="30%"
    center>

    
    <my-component :visible.sync="centerDialogVisible" :data="xxxx">my-component>

    
    <span slot="footer">
      <el-button @click="centerDialogVisible = false">取 消el-button>
      <el-button type="primary" @click="centerDialogVisible = false">确 定el-button>
    span>
  el-dialog>
template>

方式2. (推荐2) el-dialog 壳子在外,内容单独组件,后续组件可以替换为其他壳子

代码语言:javascript
复制
<template>
  <el-dialog
    title="编辑"
    :visible.sync="centerDialogVisible"
    width="30%"
    center>

    
    <my-component :visible.sync="centerDialogVisible" :id="editId">my-component>
  el-dialog>
template>

方式3. (不推荐) el-dialog 在组件内部

代码语言:javascript
复制
<my-component :visible.sync="centerDialogVisible" :id="editId">my-component>

响应方式

前提:组件内不请求数据推荐1:直接注入数据「详情」

如果是将当前 row 或者 组件外获取数据,直接传递就好(详情通常是这种场景),不在本文讨论范围内。

举例:新增/编辑使用同一组件 – (推荐2) el-dialog 壳子在外,内容单独组件,后续组件可以替换为其他壳子

问题:

  1. 数据响应触发请求,特别注意同一ID以及区分新增(无需请求)/编辑情况
  2. 表单错误提示语清空,特别注意第一次调用时,$refs['xxx'] 可能还不存在

方案

方案1. (禁用) v-if + created/mounted 写法简单,但是性能极差,万不得已杜绝使用!!!

方案2. (不建议) :key 虽性能上会比 v-if 好很多,但是这里的场景,数据响应即可解决,和 DOM(虚拟DOM)没太大关系。

代码语言:javascript
复制
<my-component :visible.sync="centerDialogVisible" :id="editId" :key="editId">my-component>

方案3. (不建议) refs.xxx.init() 调用。两个问题:第一次调用时机,往往需要 await this.$nextTick();组件内部方法被外部元素调用,耦合度高,维护和升级成本无法控制。

方案4. 监听 id 变化,然后根据 id 请求数据 编辑保存成功,点击当前行,id 并未发生变化,导致数据为变更前的 ==> 保存成功后,id = undefined,取消或者关闭不做处理。

代码语言:javascript
复制
props: ['id'],
watch: {
  id: {
    handler (val, oldVal) {
      // 新增id为undefined
      if (val) {
        this.requestData(val) // 请求后台
      }
    },
    immediate: true
  },
  visible: {
    handler (val, oldVal) {
     	!val && this.resetForm()
    },
    immediate: true
  }
}
  • 优势: 请求精准,不会存在额外请求情况
  • 劣势: 需要监听 id 和 watch,处理稍许复杂

方案5. 监听 visible 变化,然后根据 visible 请求数据

代码语言:javascript
复制
props: ['id', 'visible'],
watch: {
  visible: {
  	handler(val, oldVal) {
  		!val && this.resetForm()
  		if (val && this.id) {
  			this.getUserById()
     }
   },
   immediate: true
  }
}
  • 优势: 错误提示清除,统一处理了,实现简单
  • 劣势: 同一ID编辑,第一次不保存(信息未发生变化),第二次打开仍会请求

补充: 针对上述「方案5」,切换 ID 弹窗显示状态不发生变化,需要同时监听 ID。

下述采用了 watch function 的形式;这里同时可以采用 computed + watch 形式

代码语言:javascript
复制
created() {
  this.unwatch = this.$watch(
    () => {
    	return [this.id, this.visible];
    },
    (val, oldVal) => {
      let [id, visible] = val
      !visible && this.resetForm();
      if (visible && id) {
      	this.getUserById();
      }
    },
    {
    	immediate: true
    }
  );
},
beforeDestroy () {
	this.unwatch()
}

延展问题

编辑与新增公用同一弹窗,先编辑,后新增,由于当前弹窗是v-show形式导致保存时多余属性被提交了(如ID)。 特别注意:el-form resetFields() 并不是处理该场景,其只会重置 el-form-item prop属性值

方案1:(繁琐) 将 form 对象进行 JSON 序列号与反序列(深拷贝)

代码语言:javascript
复制
const userForm = {
  name: "",
  province: ""
}
export default {
  name: "User",
  props: ["visible", "id"],
  data() {
    return {
      userForm: JSON.parse(JSON.stringify(userForm)),
      rules: { ... }
    };
  },
  methods: {
  	resetForm() {
      this.$refs.userForm.resetFields();
      this.userForm = JSON.parse(JSON.stringify(userForm));
    }
  }
}

方案2:(局限) 提交时,删除 id(当编辑比新增属性多很多时,该方案会很冗余)

代码语言:javascript
复制
// 需要获取当前是「新增」还是「编辑」操作
delete this.userForm.id
...

方案3:(推荐) 通过 this.$options.data() 还原

代码语言:javascript
复制
resetForm() {
  this.$refs.userForm.resetFields();
  this.userForm = Object.assign({}, this.$options.data().userForm);
}

// 或更霸道,还原所有 this 数据
const data = this.$options.data()
Object.keys(data).forEach(key => {
  this[key] = data[key]
})

参考地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DOM 结构
  • 响应方式
  • 方案
  • 延展问题
  • 参考地址
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档