2017-05-05 75 views
12

这个问题类似于VueJS re-compile HTML in an inline-template component同时也How to make Vue js directive working in an appended html elementVueJs操纵联模板,并对其进行重新初始化

不幸的是在这个问题的解决不能再对当前VueJS执行情况$compile使用已被删除。

我的使用情况如下:

我不得不使用它操作的页面,之后触发一个事件的第三方代码。现在事件被解雇后,我想让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) 
+0

新代码可以显示在网页上的任何位置吗? –

+0

是的,有多个地点是动态生成的。我找到了一个解决方案,但感觉更像是一个黑客:https://jsfiddle.net/9ukmy0k0/ – jantimon

+1

琐事是不可避免的:你违反与Vue的合同,它将控制DOM。 –

回答

2

经过进一步调查,我接触到了VueJs te我并得到了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 
    } 
    } 
}) 

如果您可以澄清用例和库,我们可以帮助更多。

+0

只是为了澄清,如果你可以阐明整体功能需求,你可能会得到一个比上述“解决方法”更简洁的回答 - 在我与Vue合作的3年中,我从来没有这样做过,我真的认为答案可能在于采取不同的方法将数据, vue实例和你的第三方库。 –

+0

关键问题是我们不是只构建一个简单的应用程序,而是尝试将Vue与CMS一起使用 – jantimon