【问题标题】:Attach v-model to a dynamic element added with .appendChild in Vue.js将 v-model 附加到在 Vue.js 中使用 .appendChild 添加的动态元素
【发布时间】:2020-05-07 21:20:03
【问题描述】:

我正在使用一个没有 Vue.js 包装器的库。 该库以动态方式在 DOM 中附加元素。

我希望能够使用 Vue 将 v-model 属性绑定到这些元素,并且一旦在我的模型中附加了它们就可以使用它们。

我过去曾使用其他响应式框架(例如 Knockout.js)做到这一点,但我找不到使用 vue.js 的方法。

这样做有什么报酬吗? 我认为应该是以下几行:

var div = document.createElement('div');
div.setAttribute('v-model', '{{demo}}');
[VUE CALL] //tell vue.js I want to use this element in my model.

document.body.appendChild(div);

【问题讨论】:

  • 不幸的是,使用 Vue 等反应式框架无法直接操作 DOM :( 在从服务器迁移延迟加载 html 的旧 jQuery 应用程序时,我自己也遇到了这个问题。必须将这些 html 更改为 json 和作为对象提供给 Vue 实例。

标签: vue.js vuejs2


【解决方案1】:

您可以为您的库创建一个包装器组件,然后在其上设置自定义v-model 以获得您正在寻找的结果。由于您的库负责操作 DOM,因此您必须挂钩您的库提供的事件以确保您的模型保持最新。您可以通过确保两件事来为您的组件提供v-model 支持:

  • 它接受 value 属性
  • 它发出一个input 事件

这是一个做类似事情的例子:https://codesandbox.io/s/listjs-jquery-wrapper-sdli1 和我实现的包装器组件的截图:

<template>
  <div>
    <div ref="listEl">
      <ul ref="listUlEl" class="list"></ul>
    </div>
    <div class="form">
      <div v-for="variable in variables" :key="variable">
        {{ variable }}
        <input v-model="form[variable]" placeholder="Enter a value">
      </div>
      <button @click="add()">Add</button>
    </div>
  </div>
</template>

<script>
export default {
  props: ["value", "variables", "template"],

  data() {
    return {
      form: {}
    };
  },

  mounted() {
    this.list = new List(
      this.$refs.listEl,
      {
        valueNames: this.variables,
        item: this.template
      },
      this.value
    );

    this.createFormModels();
  },

  methods: {
    createFormModels() {
      for (const variable of this.variables) {
        this.$set(this.form, variable, "");
      }
    },

    add() {
      this.$emit("input", [
        ...this.value,
        {
          id: this.value.slice(-1)[0].id + 1,
          ...this.form
        }
      ]);
    }
  },

  watch: {
    value: {
      deep: true,
      handler() {
        this.$refs.listUlEl.innerHTML = "";

        this.list = new List(
          this.$refs.listEl,
          {
            valueNames: this.variables,
            item: this.template
          },
          this.value
        );
      }
    }
  },

  beforeDestroy() {
    // Do cleanup, eg:
    // this.list.destroy();
  }
};
</script>

关键点:

  • mounted() 上初始化自定义库以创建 DOM。如果它需要使用一个元素,请通过&lt;template&gt; 提供一个并在其上放置一个ref。这也是在您的库中设置事件侦听器的地方,以便您可以通过$emit('value', newListOfStuff) 触发模型更新。
  • watch 用于更改 value 属性,以便您可以重新初始化库,或者如果它提供了更新其集合的方法,请改用它。如果库提供对它的支持以及取消绑定事件处理程序,请确保清理以前的实例。
  • beforeDestroy 中调用任何清理操作、事件处理程序删除。

进一步参考:

【讨论】:

  • 围绕一个库创建一个完整的包装器对于这样一个简单的事情来说似乎需要做很多工作。没有更直接的方法吗?
猜你喜欢
  • 2020-04-29
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多