如何动态添加或删除 Vue.js 组件(以编程方式或即时)

Sye*_*yed 7 javascript vue.js vue-component vuejs2

这是我的代码,这只是一个示例代码,如果下面的代码有效,那么这将帮助我构建我正在处理的其他内容。

<template>
  <div id="wrapper">
    <div id="divOne">
      <!-- Add or remove component here dynamically -->
    </div>
    <div id="divTwo">
      <!-- Add or remove component here dynamically -->
    </div>

    <!-- There will be more divs like #divOne #divTwo above -->

    <div>
      <input type="radio" id="one" value="divOne" v-model="pickedDiv">
      <label for="one">One</label>
    </div>
    <div>
      <input type="radio" id="two" value="divTwo" v-model="pickedDiv">
      <label for="two">Two</label>
    </div>

    <button @click="addComponent">Add Component</button>
  </div>
</template>

<script>
import SomeComponent from './SomeComponent'

export default {
  data() {
    return {
      pickedDiv: '',
      pickedDivPreviously: ''
      propItems: ['item1', 'item2']
    }
  }
  methods: {
    addComponent () {
      //-- This is not working code but I need something like this --//
      this.pickedDivPreviously = this.pickedDiv // event not sure how to get previously selected div

      const divThatIsPicked = document.getElementById(this.pickedDiv)
      const divThatWasPickedPreviously = document.getElementById(this.pickedDivPreviously)

      // code here to remove/empty/destroy old component from 'divThatWasPickedPreviously'
      divThatWasPickedPreviously.innerHTML = "" 

      // code here to add new component in 'divThatIsPicked'
      divThatIsPicked.appendChild('<some-component :someProp="propItems" @someEvent="someFn">')
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

我不想分散您回答实际问题的注意力,但是如果您对我的工作感到好奇,请检查这个:) 在这里,当单击任何行项目时,我试图在行的末尾添加新的子 DIV。

我会更高兴,如果被转换为VUE比实际问题上面问,说,请不要误会,从实际问题分心,如果你觉得很难:)

Sye*_*yed 5

我在forum.vuejs.org中得到了 JamesThomson 的帮助,尽管该解决方案没有解决我的问题,但我开始了解使用 Vue.js 的限制或可能性。

\n\n

詹姆斯·汤姆森 说:

\n\n
\n

是的,你的示例代码肯定不会\xe2\x80\x99 工作。使用 Vue 时,您需要以面向数据的方式思考,而不是面向 DOM(如 jQuery)

\n\n

摘自您的 SO 帖子:

\n\n

在这里,当单击任何\n 行项目时,我尝试在行末尾添加新的子 DIV。

\n\n

我认为这是您本主题的最终目标。一个简单的示例\n 可以这样实现:\n https://codepen.io/getreworked/pen/XZOgbm?editors=1010

\n
\n\n

\r\n
\r\n
let Welcome = {\r\n  template: `\r\n    <p @click="toggleMsg()">Welcome {{ msg }}!</p>\r\n  `,\r\n  \r\n  data () {\r\n    return {\r\n      msg: \'home\'\r\n    }\r\n  },\r\n  \r\n  methods: {\r\n    toggleMsg () {\r\n      return this.msg = this.msg === \'home\' ? \'back\' : \'home\'; \r\n    }\r\n  }\r\n}\r\n\r\nconst App = new Vue({\r\n  el: \'#app\',\r\n  \r\n  data: {\r\n    children: [\r\n      Welcome\r\n    ]\r\n  },\r\n  \r\n  methods: {\r\n    add () {\r\n      this.children.push(Welcome);\r\n    },\r\n  }\r\n});
Run Code Online (Sandbox Code Playgroud)\r\n
<link rel="stylesheet" href="//cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css">\r\n<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>\r\n\r\n<div id="app">\r\n  <template v-for="(child, index) in children">\r\n      <component :is="child" :key="child.name"></component>\r\n  </template>\r\n  \r\n  <button @click="add()">Add Another</button>\r\n</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

\n

或者您可以使用渲染函数以获得更大的灵活性\n https://jsfiddle.net/jamesbrndwgn/ku7m1dp0/9/

\n
\n\n

\r\n
\r\n
const Reusable = {\r\n  template: \'<div>{{ name }} {{ bar }}</div>\',\r\n  \r\n  props: {\r\n    name: {\r\n      type: String\r\n    }\r\n  },\r\n  \r\n  data () {\r\n    return {\r\n      bar: \'Bar\'\r\n    }\r\n  }\r\n}\r\n\r\nconst App = new Vue({\r\n  el: \'#app\',\r\n  \r\n  data: {\r\n    items: []\r\n  },\r\n  \r\n  methods: {\r\n    addComponent () {\r\n      const renderComponent = {\r\n        render (h) {         \r\n          return h(Reusable, {\r\n            class: [\'foo\'],\r\n            \r\n            props: { \r\n              name: \'Foo\'\r\n            }\r\n          })\r\n        }\r\n      }\r\n      \r\n      this.items.push(renderComponent)      \r\n    }\r\n  }\r\n});
Run Code Online (Sandbox Code Playgroud)\r\n
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>\r\n<link rel="stylesheet" href="//cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css">\r\n\r\n<div id="app">\r\n  <component v-for="item in items" ref="itemRefs" :is="item" :key="item.name"></component>\r\n  \r\n  <button @click="addComponent">Add Component</button>\r\n</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

我发现另一种方法与上面的方法有点相同,但仅适用于旧的 vue.js-1,不适用于 vue.js-2:

\n\n

\r\n
\r\n
var createNewBox = function() {\r\n\tvar MyPartial = Vue.extend({});\r\n  window.partial = new MyPartial({\r\n    template: \'#partial\',\r\n    data: function() {\r\n      return {\r\n        txt: \'This is partial\'\r\n      }\r\n    },\r\n    methods: {\r\n    \tprint: function() {\r\n        console.log(\'this.txt : \' + this.txt)\r\n        console.log(\'main.txt : \' + main.txt)\r\n      },\r\n    },\r\n  })\r\n  window.partial.$mount().$appendTo(\'body\')\r\n}\r\n\r\nwindow.main = new Vue({\r\n  el: \'#main\',\r\n  data: function() {\r\n  \treturn {\r\n    \ttxt: \'This is main\'\r\n    }\r\n  },\r\n  methods: {\r\n  \tshow: function() {\r\n    \tcreateNewBox()\r\n    }\r\n  },\r\n})
Run Code Online (Sandbox Code Playgroud)\r\n
<script src="https://cdn.bootcss.com/vue/1.0.17/vue.min.js"></script>\r\n\r\n<div @click="show" style="width:200px;height:200px;background:#000" id="main">\r\n  <template id="partial">\r\n    <div style="width:100px;height:100px;background:#ff0" @click.stop="print"></div>\r\n  </template>\r\n</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n