首页 文章

VueJs操纵内联模板并重新初始化它

提问于
浏览
12

这个问题类似于VueJS re-compile HTML in an inline-template componentHow to make Vue js directive working in an appended html element

不幸的是,由于删除了 $compile ,该问题的解决方案不能再用于当前的VueJS实现 .

我的用例如下:

我必须使用第三方代码来操纵页面并在之后触发事件 . 在该事件被解雇之后,我想让VueJS知道它应该重新初始化当前的DOM .

(用纯JavaScript编写的第三方允许用户向页面添加新的小部件)

https://jsfiddle.net/5y8c0u2k/

HTML

<div id="app">
    <my-input inline-template>
  <div class="wrapper">
  My inline template<br>
  <input v-model="value">
  <my-element inline-template :value="value">
    <button v-text="value" @click="click"></button>
  </my-element>
  </div>
    </my-input>
</div>

Javascript - VueJS 2.2

Vue.component('my-input', {
    data() {
        return {
            value: 1000
        };
    }
});

Vue.component('my-element', {
    props: {
        value: String
    },
    methods: {
        click() {
            console.log('Clicked the button');
        }
    }
});

new Vue({
    el: '#app',
});

// Pseudo code
setInterval(() => {
  // Third party library adds html:
  var newContent = document.createElement('div');
  newContent.innerHTML = `<my-element inline-template :value="value">
     <button v-text="value" @click="click"></button>
  </my-element>`;   document.querySelector('.wrapper').appendChild(newContent)

   //      
   // How would I now reinialize the app or
   // the wrapping component to use the click handler and value?
   //

}, 5000)

2 回答

  • 2

    经过进一步调查后,我联系了VueJs团队并获得了feedback,以下方法可能是一个有效的解决方案:

    /**
     * Content change handler
     */
    function handleContentChange() {
      const inlineTemplates = document.querySelector('[inline-template]');
      for (var inlineTemplate of inlineTemplates) {
        processNewElement(inlineTemplate);
      }
    }
    
    
    /**
     * Tell vue to initialize a new element
     */
    function processNewElement(element) {
      const vue = getClosestVueInstance(element);
      new Vue({
        el: element,
        data: vue.$data
      });
    }
    
    /**
     * Returns the __vue__ instance of the next element up the dom tree
     */
    function getClosestVueInstance(element) {
      if (element) {
        return element.__vue__ || getClosestVueInstance(element.parentElement);
      }
    }
    

    您可以在以下fiddle中尝试

  • 1

    一般来说,当我听到这样的问题时,他们似乎总是通过使用Vue的一些更亲密和模糊的内在美来解决:)

    我已经使用了很多“坚持拥有数据”的第三方库,用于修改DOM - 但是如果你可以使用这些事件,你可以将更改代理到Vue拥有的对象 - 或者,如果可以的话没有vue拥有的对象,您可以通过计算属性观察独立的数据结构 .

    window.someObjectINeedtoObserve = {...}
    
    yourLib.on('someEvent', (data) => {
      // affect someObjectINeedtoObserve...
    })
    
    new Vue ({
      // ...
      computed: {
        myObject () {
          // object now observed and bound and the dom will react to changes
          return window.someObjectINeedtoObserve 
        }
      }
    })
    

    如果您可以澄清用例和库,我们可能会提供更多帮助 .

相关问题