当前位置: 首页 > 知识库问答 >
问题:

ue.jsDOM树突变后添加vue组件

申屠无尘
2023-03-14

我有一个用例(如下),我需要挂载(如果这是正确的术语)一个Vue。通过jQuery插入DOM的js组件模板,我可以设置一个突变观察者,或者对突变发生时触发的某些事件做出反应。

我正在使用Vue。JSV2

这里有一个简单的例子,我放在一起来说明这一点:

Live jsFiddlehttps://jsfiddle.net/w7q7b1bh/2/

下面的超文本标记语言包含两个组件的内联模板

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="app">
  <!-- The use of inline-template is required for my solution to work -->
  <simple-counter inline-template>
    <button v-bind:style="style" v-on:click="add">clicks: {{ counter }}</button>
  </simple-counter>
  <simple-counter inline-template>
    <button v-on:click="counter += 1">{{ counter }}</button>
  </simple-counter>
</div>

<button id="mutate">Mutate</button>

js:

// simple counter component
Vue.component('simple-counter', {
  data: function() {
    return {
      counter: 0,
      style: {
        color: 'red',
        width: '200px'
      }
    }
  },
  methods: {
    add: function() {
      this.counter = this.counter + 1;
      this.style.color = this.style.color == 'red' ? 'green' : 'red';
    }
  }
})

// create the Vue instance
var initV = () => new Vue({
  el: '#app'
});

// expose the instance for later use
window.v = initV();

// click handler that will add a new `simple-counter` template to the Vue.el scope
$('#mutate').click(function(){
    $('#app').append(`  <div is="simple-counter" inline-template>
    <button v-bind:style="style" v-on:click="add">click to add: <span class="inactive" v-bind:class="{ active: true }">{{ counter }}</span></button></div>`)
    // do something after the template is incerted
    window.v.$destroy()
    window.v = initV(); // does not work

})

正如代码中提到的,销毁重新实例化Vue实例的模板不起作用,我理解为什么在第一次Vue实例化时组件的模板会更改为最终HTML,当您尝试第二次实例化时,模板不存在,组件未装入

我希望能够找到突变后新添加的组件,并仅安装这些组件,这可能吗?怎么做?

更新:我能够找到一种方法,通过实例化一个新的Vue实例,将el设置为DOM的特定变异部分,而不是整个#app树:

$('#mutate').click(function(){
    var appended = 
            $(`
       <div is="simple-counter" inline-template>
         <button v-bind:style="style" v-on:click="add">
           click to add: {{ counter }}
         </button>
       </div>`
      ).appendTo($('#app'));

    var newV = new Vue({el: appended[0]});
});

看起来很有效,但也很难看,我不确定这可能会有什么其他的影响。。

使用案例:

我正在研究一种编写Vue的方法。用于CMS的js组件称为Adobe Experience Manager(AEM)。

我写我的组件使用内联模板,这给了我SEO的优势,以及使用另一种称为HTL的模板语言的服务器端渲染。

AEM创作的工作方式是,当编辑组件(通过对话框)时,该特定组件在服务器端重新呈现,然后注入回DOM以替换旧组件,所有操作都通过Ajax和jQuery完成(无需浏览器刷新)。

这里有个例子

AEM组件模板:

以下是作者可能会做的:

  1. 作者访问创作页面

保存后,发送一个ajax,在服务器上重新呈现组件HTML,并返回新的HTML。该HTML现在通过jQuery替换了旧的HTML(改变了DOM)

这对于静态组件很好,但如果这是Vue。js组件,我如何动态地挂载它,同时保持其他组件的挂载。

一个简单的解决方法是刷新页面。。。但那只是糟糕的经历。。。一定有更好的办法。


共有2个答案

严正诚
2023-03-14

在运行时生成的超文本标记语言中实例化Vue组件的一种方法是:

var ComponentClass = Vue.extend({
    template: '...',
});
var instance = new ComponentClass({
    propsData: { name: value },
});
instance.$mount('#uid'); // HTML contains <... id="uid">
...
instance.$destroy(); // if HTML containing id="uid" is dropped

这里有更多信息(我不属于此网站)
https://css-tricks.com/creating-vue-js-component-instances-programmatically/

荀子轩
2023-03-14

感谢@liam,我能够找到一个合适的解决方案来解决我的问题

使用HTML模板修改DOM后,保留对该模板父元素的引用

例如:

var $template = $('<div is="simple-counter" inline-template> ..rest of template here.. <div>').appendTo('#app') // app is the Vue instance el or a child of it

现在,您可以创建组件的新实例,并将$template作为el属性添加到其中

如果我的组件是:

var simpleCounterComponent = Vue.component('simple-counter', {
  data: function() {
    return {
      counter: 0,
      style: {
        color: 'red',
        width: '200px'
      }
    }
  },
  methods: {
    add: function() {
      this.counter = this.counter + 1;
      this.style.color = this.style.color == 'red' ? 'green' : 'red';
    }
  }
})

我可以做到:

var instance = new simpleCounterComponent({
  el: $template.get(0) // getting an HTML element not a jQuery object
});

这样,新添加的模板就变成了Vue组件

看看这个基于问题的小提琴工作示例:

https://jsfiddle.net/947ojvnw/11/

 类似资料:
  • 我正在尝试向使用Apollo的GraphQL服务器发送突变查询。 然而,我只看到实现这一点的唯一方法是使用突变组件。https://www.apollographql.com/docs/react/essentials/mutations/#the-突变成分 有没有一种简单的方法可以发送这样的突变? 从“graphql标记”导入gql;

  • 我有一个Vue组件(Highlight.vue),现在写一个Markdown组件,要复用这个Highlight.vue组件,markdown中解析代码模块是通过js回调方式的,示例如下: 各位大佬,有没有办法解决这种插入vue组件代码的?

  • 我们试图使用以下源代码在组合框中显示树状结构https://fiddle.sencha.com/#fiddle/g50 我们可以在组合框中查看树结构,但是当我们选择任何节点时,它不会显示在组合框中。

  • 问题内容: 有人可以告诉我如何摆脱BeanCreationException吗? 在向Owner.java中添加两个变量之后,我得到了BeanCreationException,如下所示: 我还添加了用于猫和狗的getter和setter方法,以及将猫和狗作为宠物子集填充的方法,如下所示: 当我在Eclipse中在服务器上运行方式为…运行时,应用程序无法初始化,并显示以下错误消息: 这是busin

  • 问题内容: 我想在运行时按下按钮时向JFrame中添加一些新组件。到目前为止,该方法仍然有效,但是我必须手动调整窗口大小才能看到新组件。 有什么我可以触发的动作或可以调用的方法来刷新窗口吗?任何帮助表示赞赏。提前致谢。 问题答案: 你必须去框架。如果这样不起作用,您还必须致电

  • 问题内容: 在检测播放器与许多相同对象(在本例中为墙砖)之间的碰撞时,我遇到了一个问题。问题是我的程序仅在与 最后添加的 墙砖接触时才检测到碰撞。这是用java写的… 我正在使用矩形(它们的相交方法)来检测碰撞。 代码示例: 更新图块: 这是我的课程,使墙从砖块中脱颖而出: } 这是我的班级,使房间或房屋带有墙壁: } 将图块和墙壁添加到其arrayList中的代码: 在wallTile.java