一、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.accessToken });// 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 远程搜索分页优化
实现要点:
-
自定义指令处理滚动触底事件
-
结合分页参数与搜索关键词
-
防抖处理搜索请求
二、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:全局方法,可以在任何地方使用,包括组件外部。
示例
// 在组件内部使用 $setthis.$set(this.someObject, 'newProperty', 'value');// 在组件外部使用 Vue.setVue.set(someObject, 'newProperty', 'value');
4. Refs 使用指南与陷阱
最佳实践:
// 声明引用
<component ref="childComp"></component>// 安全访问
mounted() {this.$nextTick(() => {this.$refs.childComp.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 开发效率,避免常见陷阱,构建更健壮的前端应用。