【问题标题】:How to Add or Remove Vue.js component dynamically (programmatically or on the fly)如何动态添加或删除 Vue.js 组件(以编程方式或动态)
【发布时间】:2018-09-24 10:11:18
【问题描述】:

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

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

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

如果this 被转换为 vue 比上面提出的实际问题,我会非常高兴,如上所述,如果你觉得很难,请不要从实际问题中分心:)

【问题讨论】:

标签: javascript vue.js vuejs2 vue-component


【解决方案1】:

this 转换为 Vue。

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

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

【讨论】:

  • 感谢您的帮助。仍然存在问题,根据行项目的内容宽度,我们不确定一行中有多少项目,因此不确定在哪里添加 &lt;div class="new-child" v-if="[x,y,z].indexOf(showNewChild) &gt; -1"&gt;boom&lt;/div&gt;
  • 如前所述,如果您觉得困难,请不要从实际问题上分心,感谢您的帮助,谢谢。
【解决方案2】:

我在forum.vuejs.org 获得了 JamesThomson 的帮助,虽然该解决方案没有解决我的问题,但我了解了使用 Vue.js 的局限性或可能性。

詹姆斯汤姆森说:

是的,你的示例代码肯定行不通。使用 Vue 时 你需要以面向数据的方式思考,而不是面向 DOM(比如 jQuery)

取自您的 SO 帖子:

在这里,我尝试在行尾添加新的子 DIV 行项目被点击。

我认为这是您对该主题的最终目标。一个简单的例子 这可以像这样实现: 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>

或者您可以使用渲染功能以获得更大的灵活性 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>

我发现了一种与上面类似但仅适用于旧 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2013-11-28
    • 2021-03-28
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多