You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Vue.js 2动态添加表格行无法应用data属性值与CSS样式

解决Vue动态添加表格行无法绑定数据与样式的问题

Hey there, let's break down why your dynamically added rows aren't working as expected, and fix it the Vue way.

问题根源

你现在用原生JS直接插入DOM的方式有两个致命问题:

  1. Vue不会编译动态插入的HTML:你插入的<select>里的v-forv-bind这些Vue指令,Vue根本不会识别和编译,所以chargesOpt里的选项完全渲染不出来。
  2. Scoped样式无法作用于动态DOM:你的<style>加了scoped,Vue会给所有组件内的模板元素添加一个专属属性(比如data-v-xxxxxx),动态插入的DOM没有这个属性,所以你的form-control3等样式无法生效。

正确解决方案:用Vue响应式数据驱动表格行

Vue的核心是数据驱动视图,我们不需要手动操作DOM,只需要用一个响应式数组存储所有行的数据,通过v-for渲染即可。新增行时只需要往数组里推一条数据,Vue会自动帮我们完成DOM更新、指令编译和样式应用。

修改后的完整代码:

<template>
  <b-card id="showBill">
    <div class="table-responsive col-md-6">
      <table class="table table-striped table-bordered table-sm" id="tbl">
        <thead>
          <tr>
            <th>Charges</th>
            <th>Amount</th>
          </tr>
        </thead>
        <tbody>
          <!-- 用v-for渲染所有行,绑定唯一key值 -->
          <tr v-for="(row, index) in billRows" :key="index">
            <td>
              <select class="form-control input-sm form-control3">
                <option v-for="option in chargesOpt" :value="option.value" :key="option.value">
                  {{ option.text }}
                </option>
              </select>
            </td>
            <td>
              <!-- 用v-model绑定行的金额数据,方便后续计算总和 -->
              <input type="text" class="form-control input-sm form-control3" v-model="row.amount">
            </td>
          </tr>
        </tbody>
        <tfoot>
          <tr class="table-secondary">
            <th>Total Amount</th>
            <!-- 实时计算总金额 -->
            <th style="text-align:right;">{{ totalAmount.toFixed(2) }}</th>
          </tr>
        </tfoot>
      </table>
    </div>
    <div class="col-md-6">
      <button type="button" class="btn btn-success" @click="addRow">Add</button>
    </div>
  </b-card>
</template>
<script>
export default {
  data () {
    return {
      chargesOpt:[
        { value: '', text: 'Select'},
        { value: '1', text: 'Maintanence'},
        { value: '2', text: 'Extra'}
      ],
      // 用响应式数组存储所有行数据,初始默认一条空行
      billRows: [{ amount: '' }]
    }
  },
  computed: {
    // 计算属性实时计算总金额,自动响应数据变化
    totalAmount() {
      return this.billRows.reduce((sum, row) => {
        const amount = parseFloat(row.amount) || 0
        return sum + amount
      }, 0)
    }
  },
  methods:{
    addRow() {
      // 新增行只需往数组push一条空数据,Vue自动渲染新行
      this.billRows.push({ amount: '' })
    }
  }
}
</script>
<style lang="scss" scoped>
@import '../../../node_modules/bootstrap/dist/css/bootstrap.min.css';
.is-danger{
  color: RED;
}
.form-control{display:block;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out }
.input-sm{
  border: 1px solid #ccc;
  padding: 5px 8px;
  color: #616161;
  background: #fff;
  box-shadow: none !important;
  width: 100%;
  font-size: 0.85em;
  font-weight: 300;
  height: 40px;
  border-radius: 0;
  -webkit-appearance: none;
  resize: none;
}
.input-sm {
  font-size: 14px;
  height: 35px;
}
.form-control3 {
  /* For Vacancy List Table Input Fields */
  padding-bottom: 0px;
  padding-top: 0px;
  background-color: transparent!important;
  background: transparent !important;
  border: 1px solid transparent !important;
  border-radius: 5px;
  box-shadow: none !important;
}
.form-control3:focus {
  border: 1px solid #03a9f4 !important;
  background: #fff !important;
  box-shadow: none !important;
}
.form-control3{
  height: 30px;
}
.form-control3{
  padding-bottom: 0px;
  padding-top: 0px;
}
</style>

方案优势

  • 数据与视图自动同步:所有行的渲染、更新都由响应式数组驱动,无需手动操作DOM,彻底避免指令不生效的问题。
  • Scoped样式正常作用:新行是Vue通过模板渲染的,会自动带上scoped样式所需的专属属性,样式完美生效。
  • 可扩展性更强:新增了总金额计算功能,后续如果需要删除行、校验数据等,只需要操作billRows数组即可,代码更易维护。

不推荐的原生DOM方案(仅作参考)

如果你非要用原生JS插入行,需要解决两个问题:

  1. 手动编译Vue模板:用Vue.compile编译插入的HTML片段,再挂载到目标元素上,但这会增加代码复杂度,违背Vue的设计思想。
  2. 穿透Scoped样式:把需要作用于动态元素的样式移出scoped,或者用::v-deep .form-control3强制穿透,但这会扩大样式作用范围,可能引发样式冲突。

还是强烈建议用响应式数组的方案,这是Vue开发的最佳实践。

内容的提问来源于stack exchange,提问作者Ashwini

火山引擎 最新活动