javascript - Vue.js 在 DOM 树突变后挂载组件以添加 vue 组件

标签 javascript vue.js vuejs2 aem

我有一个用例(如下)我需要 mount (如果这是正确的术语)通过 jQuery 插入到 DOM 中的 Vue.js 组件模板,我可以设置一个 Mutation Observer 或对发生突变时触发的某些事件使用react。

I am using Vue.js v2

我举了一个简单的例子来说明这一点:

live jsFiddle https://jsfiddle.net/w7q7b1bh/2/

下面的 HTML 包含 inlined-templates对于两个组件

<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,模板不存在,组件不存在 mounted

我希望能够在变异后找到新添加的组件并只挂载那些,这可能吗?以及如何?

更新: 我能够通过实例化一个新的 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]});
});

似乎可行,但看起来也很丑,我不确定这可能还有什么其他含义..

用例:

我正在研究一种为名为 Adob​​e Experience Manager (AEM) 的 CMS 编写 Vue.js 组件的方法。

我使用 inlined-template 编写我的组件这给了我 SEO 的优势,以及使用另一种称为 HTL 的模板语言进行服务器端呈现的优势。

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

举个例子

AEM 组件模板: <button>${properties.buttonTitle}</button>

这是作者可能会做的事情:

  1. 作者访问创作页面
  2. 打开按钮组件对话框进行编辑
  3. 将按钮标题更改为“新按钮标题”
  4. 保存

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

这对于静态组件来说没问题,但如果这是一个 Vue.js 组件,我该如何在保持其他组件挂载的同时动态挂载它。

An easy solution to this is to refresh the page... but that is just bad experience... There has to be a better way.

最佳答案

感谢@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组件

根据以下问题查看此 fiddle 的工作示例:

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

关于javascript - Vue.js 在 DOM 树突变后挂载组件以添加 vue 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48837002/

相关文章:

Javascript正则表达式错误,两个字符之间的文本

javascript - YUI3 对象和带有模块的命名空间

javascript - 如何在 Vue.js 中使用 ListView ?

javascript - UglifyJs 中的 build.js 中出现错误 意外 token : punc (()

vue.js - 在v-card中的v-img内添加 float 按钮

javascript - 我对 DOM 操作有点迷茫

javascript - 鼠标指针不会隐藏在 chrome 全屏 div 上

javascript - 如何在 v-time-picker 中禁用选择分钟?

azure - 根据 Auth0 在本地对 Vue 2 Azure 静态 Web 应用程序进行身份验证

vue.js - Vue.js 中所有导入的数组都必须是响应式的吗?