简体   繁体   English

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

[英]How to Add or Remove Vue.js component dynamically (programmatically or on the fly)

Here is my code, this is just a example code, if the below works then this will help me to build something else that I am working on. 这是我的代码,这只是一个示例代码,如果以下工作,那么这将帮助我构建我正在处理的其他东西。

<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>

I don't want to distract you from answering actual question but If you are curious about what I am working then check this :) Here I am trying to add new child DIV at the end of the row when any row item is clicked. 我不想分散您对实际问题的回答,但如果您对我正在工作的内容感到好奇,那么请检查一下 :)这里我想在单击任何行项目时在行的末尾添加新的子DIV。

I will be more than happy if this is converted to vue than the actual question asked above, as said please don't get distracted from actual question if you find it hard :) 我会很乐意,如果这个转换比上面提出的实际问题VUE,如说请不要误会,从实际问题分心,如果你觉得很难:)

I got help from JamesThomson in forum.vuejs.org , though the solution did not fix my issue but I got to understand the limitation or possibilities of using Vue.js. 我在forum.vuejs.org得到了JamesThomson的帮助 ,虽然解决方案没有解决我的问题,但我了解使用Vue.js的限制或可能性。

JamesThomson says: 詹姆斯汤姆森说:

Yeah, your example code definitely won't work. 是的,你的示例代码肯定不会起作用。 When working with Vue you need to think in a data oriented way, not DOM oriented (like jQuery) 使用Vue时,您需要以面向数据的方式思考,而不是面向DOM(如jQuery)

Taken from your SO post: 取自您的SO帖子:

Here I am trying to add new child DIV at the end of the row when any row item is clicked. 在这里,我尝试在单击任何行项目时在行的末尾添加新的子DIV。

I assume this is your end goal for this topic. 我认为这是本主题的最终目标。 A simple example of this can be achieved like so: https://codepen.io/getreworked/pen/XZOgbm?editors=1010 一个简单的例子可以这样实现: https//codepen.io/getreworked/pen/XZOgbm?editors = 1010

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

or you can use a render function for more flexibility https://jsfiddle.net/jamesbrndwgn/ku7m1dp0/9/ 或者您可以使用渲染功能获得更大的灵活性https://jsfiddle.net/jamesbrndwgn/ku7m1dp0/9/

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

I found one of the other ways that does kinda same as above but work only with old vue.js-1 not with vue.js-2: 我找到了其他一种与上面相同的方法,但只使用旧的vue.js-1而不是vue.js-2:

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

this converted to Vue. 转换为Vue。

https://codepen.io/jacobgoh101/pen/Kojpve https://codepen.io/jacobgoh101/pen/Kojpve

<div id="app">
  <div class="parent">
    <div class="child" @click="handleChildClick" data-new-child-id="1">1234</div>

    <div class="child" @click="handleChildClick" data-new-child-id="2">12341234 </div>

    <div class="child" @click="handleChildClick" data-new-child-id="3">123412341234</div>

    <div class="child" @click="handleChildClick" data-new-child-id="4">1234</div>

    <div class="new-child" v-if="[1,2,3,4].indexOf(showNewChild) > -1">boom</div>

    <div class="child" @click="handleChildClick" data-new-child-id="5">12341234</div>

    <div class="child" @click="handleChildClick" data-new-child-id="6">123412341234</div>

    <div class="child" @click="handleChildClick" data-new-child-id="7">1234</div>

    <div class="child" @click="handleChildClick" data-new-child-id="8">12341234</div>

    <div class="new-child" v-if="[5,6,7,8].indexOf(showNewChild) > -1">boom</div>

    <div class="child" @click="handleChildClick" data-new-child-id="9">123412341234</div>

    <div class="new-child" v-if="[9].indexOf(showNewChild) > -1">boom</div>
  </div>
</div>

Javascript 使用Javascript

new Vue({
  el: '#app',
  data: {
    showNewChild:null
  },
  methods: {
    handleChildClick(e) {
      let id = e.target.dataset.newChildId;
      id = Number(id);
      this.showNewChild = id;
    }
  }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM