积累-Vue.js 开发实用指南:ElementUI 与核心技巧

积累-Vue.js 开发实用指南:ElementUI 与核心技巧

一、ElementUI 组件高效使用

1. Table 组件展开行优化实现

场景需求:仅在展开行时动态加载数据,避免不必要的接口调用

实现方案

// expand行展开的时候调用
        expandOpen: async (row, expandedRows) => {
          // 实时更新展开列
          const index = expandedRows.indexOf(row);
          this.expandedRows = expandedRows;
          if (index !== -1) {
            // 检查是否已经获取过数据,避免重复请求
            if (!row.hawbs) {
              // let res = await findHawbByMawbId({ mid: row.mawbId }, { Authorization: 'Bearer ' + this.$store.state.UserInfo.a***essToken });
              // row.hawbs = res;
             }
          }
        },
        columns: [
          {
            type: "expand",
            fixed: "left",
            render: (h, params) => {
              // if (this.expandedRows.includes(params.row)) {
                params.row.hawbs.mawbId = params.row.mawbId;
                return <Table data={params.row.hawbs} />;
              // }
            }
          },
@expand-change = "cfgs.expandOpen"

关键点

  • 使用 expand-change 事件监听展开状态变化

  • 通过 expandedRows 数组跟踪当前展开的行

  • 检查数据是否已加载避免重复请求

2. 表单编辑/新增模式下的重置陷阱

问题现象

  • 先新增后编辑:正常

  • 先编辑后新增:resetFields() 失效

根本原因

  • resetFields() 是将表单重置为初始值而非清空

  • 编辑时赋值操作改变了表单初始值

  • 在没有点新增或着编辑时,我的el-dialog弹出框里的内容是空白的,只有header和footer,

    并没有body,只有el-dialog弹出时才会加载内容。

解决方案

edit(row) {
  this.visible = true;
  this.$nextTick(() => {
    // 确保DOM更新完成后再赋值
    this.form = { ...row };
  });
}

3. Select 远程搜索分页优化

实现要点

  1. 自定义指令处理滚动触底事件

  2. 结合分页参数与搜索关键词

  3. 防抖处理搜索请求

二、Vue 核心操作技巧

1. $nextTick 的正确使用

典型场景

  • 在数据变化后操作 DOM

  • DOM 更新后的元素操作

  • 确保多个更新顺序执行

  • 解决异步渲染导致的问题

代码示例

this.someData = newValue;
this.$nextTick(() => {
  // 此时DOM已更新
  this.$refs.myElement.scrollIntoView();
});

Vue 3 改进

  • 基于 Proxy 的响应式系统

  • 直接修改即可触发更新

2.this.$set(this.someObject, 'newProperty', 'newValue');

Vue2 新增响应式属性。

在 Vue 2 中,响应式数据的更新非常重要,因为它确保了当数据改变时,视图能够自动更新。Vue 使用一套高效的机制来追踪依赖并在数据变化时更新视图。然而,在某些情况下,直接修改对象的属性可能不会触发视图更新。这时,$set 方法就显得尤为重要。

a. $set 方法简介

$set 是 Vue 实例的一个方法,用于向响应式对象添加一个新的属性,并确保新属性同样是响应式的,能够触发视图更新。

语法

Vue.set(target, propertyName, value)

target:要添加属性的对象。

propertyName:要添加的新属性的名称。

value:新属性的值。

b. 为什么需要 $set

在 Vue 中,只有通过 data 函数声明的属性才是响应式的。如果你在实例创建之后直接添加新的属性,那么这个属性不是响应式的,不会触发视图更新。

示例

export default {

  data() {

    return {

      object: {}

    };

  },

  mounted() {

    this.object.newProperty = 'newValue'; // 直接添加属性,不会触发视图更新

    this.$set(this.object, 'newProperty', 'newValue'); // 使用 $set 添加属性,会触发视图更新

  }

}

在这个例子中,直接给 object 添加 newProperty 属性不会触发视图更新,而使用 $set 方法添加则可以。

c. $set 的使用场景
  • 动态添加属性

当你需要在运行时动态添加新的属性到对象中时,使用 $set 可以确保新属性是响应式的。

示例

methods: {

  addProperty() {

    this.$set(this.someObject, 'dynamicProperty', 'value');

  }

}
  • 修改数组索引

虽然 Vue 能够自动追踪数组的变化,但是直接通过索引修改数组项可能不会触发更新。使用 $set 可以确保更新是响应式的。

示例

methods: {

  updateItem(index, newValue) {

    this.$set(this.items, index, newValue);

  }

}

3.$set 与 Vue.set 的区别

$set:Vue 实例方法,只能在组件实例中使用。

Vue.set:全局方法,可以在任何地方使用,包括组件外部。

示例

// 在组件内部使用 $set

this.$set(this.someObject, 'newProperty', 'value');

// 在组件外部使用 Vue.set

Vue.set(someObject, 'newProperty', 'value');

4. Refs 使用指南与陷阱

最佳实践

// 声明引用
<***ponent ref="child***p"></***ponent>

// 安全访问
mounted() {
  this.$nextTick(() => {
    this.$refs.child***p.doSomething();
  });
}

常见问题

  • refs在DOM渲染完成后才能使用

    • Vue在渲染DOM时是异步的,因此refs只有在DOM渲染完成后才能访问。如果尝试在DOM渲染之前访问refs,将会得到undefined。解决方法是使用生命周期钩子mounted或者在nextTick中访问refs。

      mounted() {
      
        this.$nextTick(() => {
      
          console.log(this.$refs.myInput); // 现在可以安全地访问refs
      
        });
      
      }
  • v-for和refs结合使用时的注意事项

    • 当在v-for循环中使用refs时,如果为每个元素指定相同的ref名称,Vue会自动将它们作为一个数组处理。这意味着this.$refs.myElement将是一个数组,而不是单个元素。

      <template>
      
        <div v-for="item in items" :key="item.id" :ref="'myElement' + item.id"></div>
      
      </template>

      在这种情况下,你需要使用数组索引来访问特定的元素:

      methods: {
      
        getElementByIndex(index) {
      
          console.log(this.$refs['myElement' + this.items[index].id][0]);
      
        }
      
      }
  • 避免过度依赖 refs 进行组件通信

    • 虽然refs非常强大,但过度使用它们可能会导致组件难以维护。在大多数情况下,你应该优先考虑使用事件和props来与子组件通信。

5. 数组初始化陷阱

存在引用问题

所有数组元素都是同一个数组的引用。这意味着当你修改其中一个子数组时,所有子数组都会受到影响。

错误示范

// 所有元素引用同一个数组!
const arr = new Array(3).fill([]);
arr[0].push(1); // 所有子数组都会受影响
console.log(arr); // 输出: [[1], [1], [1]]
const arr = [];
for (let i = 0; i < 3; i++) {
  arr.push([]);
}

三、Scoped CSS 深度作用

第三方组件样式覆盖方案

问题分析

  • 域限制-Scoped 生成的 data-v-xxx 属性不传递到子组件
    • scoped 生成的 data-v-xxxx 属性仅存在于当前组件的 DOM 元素上,而第三方组件内部的元素不会继承该属性。例如:

      <!-- 当前组件模板 -->
      
      <el-button class="my-btn">按钮</el-button>
      
      <!-- 渲染后的第三方组件 DOM -->
      
      <button class="el-button el-button--primary" data-v-第三方hash>
      
        <span class="el-button__text">按钮</span>
      
      </button>

      此时 .my-btn[data-v-current] 无法匹配到第三方组件的元素。

  • 选择器不匹配-常规选择器无法匹配子组件内部元素
    • 直接编写的选择器(如 .el-button__text)会被编译为 .el-button__text[data-v-current],但第三方组件内部元素可能没有此属性,导致样式失效。

解决方案对比

语法 示例 适用场景
>>> .parent >>> .child 原生CSS
/deep/ .parent /deep/ .child 已废弃
::v-deep .parent::v-deep .child 推荐用法

实现示例

/* 最终编译为 [data-v-xxx] .el-button__text */
.my-btn::v-deep .el-button__text {
  color: red;
}

注意事项

  • 避免全局样式污染

  • 尽量缩小样式作用范围

  • 优先使用组件提供的样式定制接口

通过掌握这些关键技巧,可以显著提升 Vue.js 开发效率,避免常见陷阱,构建更健壮的前端应用。

转载请说明出处内容投诉
CSS教程网 » 积累-Vue.js 开发实用指南:ElementUI 与核心技巧

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买