【问题标题】:Vue V-Model Initiation Losses Selects SelectionVue V-Model Initiation Loss Selects 选择
【发布时间】:2019-03-14 17:45:06
【问题描述】:

我在某些类型的 html 元素上初始化 Vue 时遇到问题,请查看以下代码:

new Vue({
  el: '#app',
  data: {
    test: ''
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  Without Vue:
  <!-- Non-Vue select defaults to selected value -->
  <select>
    <option>1</option>
    <option selected>2</option>
    <option>3</option>
  </select>

  <br /> 
  <br /> 
  
  With Vue:
  <!-- Vue enabled list loses selection -->
  <select v-model="test">
    <option>1</option>
    <option selected>2</option>
    <option>3</option>
  </select>
</div>

当我启动 Vue 时,您声明 v-Modal 的任何“选择”似乎都失去了它们的选择值。这如the documentation 中所述:

v-model 将忽略初始值、选中或选中的属性 在任何表单元素上都可以找到。它将始终处理 Vue 实例数据 作为真理的来源。您应该在 JavaScript 端,在组件的 data 选项中。

现在我可以做到这一点,但是对于每个选择,我现在需要在 Vue 之外编写一些 JS 来填充/重新填充选择的默认值(通过填充“数据”属性,或者重新选择之前选择的值发布 Vue减速)。

有没有更简单的方法来做到这一点?也许我可以将某种选项或标签提供给 Vue 以“持久”从 HTML 控件的初始状态继承的值?

【问题讨论】:

  • 为什么不为 data 属性 = test 分配一个与 test: 2 等选项之一相同的默认值?
  • 是的,我做过类似var XXX = $('#XXX').val(); ... vueObject.data = XXX 之类的事情,但基本上是一样的,是的,您的方法可能比我使用的更hacky 的解决方法更好。我知道有办法绕过这种行为,我只是想要一些更简单的东西。带有许多下拉菜单的大型用户表单变得非常乏味......

标签: javascript html vuejs2 html-select v-model


【解决方案1】:

要利用vue 的反应系统,vue 需要完全控制。所以没有办法,你必须以某种方式通知vue这些默认值。

如果你以 html 为中心,那会有点尴尬:你必须选择 dom 元素来找到它的默认值并将其设置回 vue。这可行,但它会是单调的。

vue 的正确做法是完全数据驱动,根据数据构建 HTML。例如,如果您的表单有 2 个选择框,那么使用 vue 的方式,您应该为您拥有的所有 options 定义数据,并使用这些数据从头开始生成这些元素(请注意,我是此处使用Single File Component 格式):

<template>
  <div>
    <Select :items="list1"/>
    <Select :items="list2"/>
  </div>
</template>
<script>
import Select from './components/Select.vue';

export default {
  data() {
    return {
      list1: [
        { id: 1, name: "spoon" },
        { id: 2, name: "fork", preselect: true },
        { id: 3, name: "knife" }
      ],
      list2: [
        { id: 4, name: "macbook" },
        { id: 5, name: "dell" },
        { id: 6, name: "lenovo", preselect: true }
      ]
    };
  },
  components: { Select }
};
</script>

还有,这是&lt;Select&gt; 组件的代码(请注意,这是一个自定义的 Vue 组件,因为它以大写字母 S 开头)。该组件将接收 propitems,并根据给定的项目自动计算选定的值:

<template>
  <select v-model="selected">
    <option 
      v-for="item of items"
      :key="item.id"
      :value="item.id">
        {{ item.name }}
    </option>
  </select>
</template>
<script>
export default {
  props: ["items"],
  data() {
    return {
      // pre-select item from 'items'
      selected: this.items.filter(item => item.preselect)[0].id
    };
  }
};
</script>

完成后,项目fork 和项目lenovo 将根据数据要求预先选择。您还可以在 codesandbox 上看到一个工作示例。

【讨论】:

  • 是的,如果我不尝试在遗留的 webforms 应用程序之上实现,那就太好了,现在我的挑战是将 vue 放在一堆“asp:DropDownList”之上,也许我需要重做所有这些......
  • @DavidRogers 我感受到了你的痛苦。当你决定有一天使用完全惯用的 Vue 时,如果你也一直在使用 seleniumpuppeteer 进行网络抓取/e2e 测试,你绝对可以创建一个脚本来查找所有 &lt;input&gt;&lt;select&gt; 元素并从那里构建数据。对于一个非常大的遗留应用程序中的大表单,手动构建 JSON 太多了。
【解决方案2】:

@b0nyb0y 的回答在技术上是正确的,但由于它不能解决我的具体问题,我想我会在此处包含我的 hacky 解决方法以供将来参考(仅适用于选择):

var itemsToRestore = [];
$('select[v-model]').each(function (index, value) {
    itemsToRestore.push({
        vModelProperty: $(value).attr("v-model"),
        selectedValue: $(value).val()
    });
});

var thisVue = new Vue({
    //Put your vue code here
});

itemsToRestore.forEach(function (value) {
    thisVue[value.vModelProperty] = value.selectedValue;
});

【讨论】:

    猜你喜欢
    • 2020-12-03
    • 2021-08-26
    • 2019-08-12
    • 2020-03-31
    • 2022-07-15
    • 2023-02-03
    • 2015-12-15
    • 2019-07-28
    • 2018-02-14
    相关资源
    最近更新 更多