Vue.js中如何通过$refs修改<span>元素的文本内容?
Vue中通过$refs修改v-for生成的文本无效问题解决
问题场景
在Vue的<template>中定义了如下<span>元素:
<span ref="span-1">my text</span>
尝试在<script>中通过$refs将其内容从my text修改为my new text,测试了以下写法(搭配innerHTML、innerText、text等属性)均未生效:
this.$refs["span-" + 1].span.value = "my new text"; this.$refs["span-" + 1].value = "my new text";
使用.span时会触发错误:
Uncaught TypeError: Cannot set properties of undefined (setting 'value')
不使用.span时,仅会给$refs对象新增属性,但<span>的实际文本内容无变化。
实际业务代码
表格模板
<table class="table"> <thead> <tr> <th v-for="(column, index) in columns" :key="index" @click="sortRecords(index)" > {{column}} <span :ref="'span-' + index"></span> </th> </tr> </thead> <tbody> <tr v-for="(row, index) in rows" :key="index" > <td v-for="(rowItem, itemIndex) in row" :key="itemIndex" > {{rowItem}} </td> </tr> </tbody> </table>
排序函数
sortRecords (index) { console.log(this.$refs); if(this.sortIndex === index){ switch(this.sortDirection){ case null: this.sortDirection = 'asc'; this.$refs["span-" + index].textContent = "my new text"; break; case 'asc': this.sortDirection = 'desc'; this.$refs["span-" + index].textContent = "my new text"; break; case 'desc': this.sortDirection = null; this.$refs["span-" + index].textContent = "my new text"; break; } } }
关键差异点
测试非v-for生成的<span>时,使用.textContent可正常修改文本;对比发现:
- 非循环生成的元素,
$refs中对应的是单个DOM对象 v-for循环生成的元素,$refs中对应的是DOM对象数组
解决方法
方法1:修正$refs取值方式(直接操作DOM)
因为v-for生成的元素在$refs中是数组,需先取数组中的目标元素再修改内容:
sortRecords (index) { console.log(this.$refs); if(this.sortIndex === index){ // 取出v-for生成的span数组中的第一个元素 const targetSpan = this.$refs["span-" + index][0]; switch(this.sortDirection){ case null: this.sortDirection = 'asc'; targetSpan.textContent = "↑"; break; case 'asc': this.sortDirection = 'desc'; targetSpan.textContent = "↓"; break; case 'desc': this.sortDirection = null; targetSpan.textContent = ""; break; } } }
方法2:数据驱动视图(Vue推荐方案)
避免直接操作DOM,通过绑定数据来控制文本内容:
- 在
data中新增存储排序状态的数组:
data() { return { columns: [], // 你的列数据 rows: [], // 你的行数据 sortIndex: null, sortDirection: null, sortIcons: [] // 存储每列的排序文本/图标 } }, created() { // 初始化数组长度与列数一致,默认空文本 this.sortIcons = new Array(this.columns.length).fill(""); }
- 修改模板绑定数据:
<th v-for="(column, index) in columns" :key="index" @click="sortRecords(index)" > {{column}} <span>{{sortIcons[index]}}</span> </th>
- 更新排序函数操作数据:
sortRecords (index) { if(this.sortIndex === index){ switch(this.sortDirection){ case null: this.sortDirection = 'asc'; this.sortIcons[index] = "↑"; break; case 'asc': this.sortDirection = 'desc'; this.sortIcons[index] = "↓"; break; case 'desc': this.sortDirection = null; this.sortIcons[index] = ""; break; } } else { // 切换列时重置状态 this.sortIndex = index; this.sortDirection = 'asc'; this.sortIcons.fill(""); this.sortIcons[index] = "↑"; } // 执行你的排序逻辑 }
内容的提问来源于stack exchange,提问作者Petar Yakov
相关产品推荐
相关产品推荐

