this question is similar to VueJS re-pile HTML in an inline-template ponent and also to How to make Vue js directive working in an appended html element
Unfortunately the solution in that question can't be used anymore for the current VueJS implementation as $pile
was removed.
My use case is the following:
I have to use third party code which manipulates the page and fires an event afterwards. Now after that event was fired I would like to let VueJS know that it should reinitialize the current DOM.
(The third party which is written in pure javascript allows an user to add new widgets to a page)
/
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
Vueponent('my-input', {
data() {
return {
value: 1000
};
}
});
Vueponent('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 ponent to use the click handler and value?
//
}, 5000)
this question is similar to VueJS re-pile HTML in an inline-template ponent and also to How to make Vue js directive working in an appended html element
Unfortunately the solution in that question can't be used anymore for the current VueJS implementation as $pile
was removed.
My use case is the following:
I have to use third party code which manipulates the page and fires an event afterwards. Now after that event was fired I would like to let VueJS know that it should reinitialize the current DOM.
(The third party which is written in pure javascript allows an user to add new widgets to a page)
https://jsfiddle/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.ponent('my-input', {
data() {
return {
value: 1000
};
}
});
Vue.ponent('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 ponent to use the click handler and value?
//
}, 5000)
Share
Improve this question
edited May 23, 2017 at 10:31
CommunityBot
11 silver badge
asked May 5, 2017 at 12:35
jantimonjantimon
38.2k23 gold badges126 silver badges193 bronze badges
6
- Can the new code show up absolutely anywhere on the page? – Roy J Commented May 5, 2017 at 15:15
- Yes there are multiple locations which are generated dynamically. I found a solution but it feels more like a hack: jsfiddle/9ukmy0k0 – jantimon Commented May 5, 2017 at 15:55
- 1 The hackiness is unavoidable: you're violating the contract with Vue that it will control the DOM. – Roy J Commented May 5, 2017 at 16:15
- That's the pain during large projects and existing solutions - you can't get in control of everything :( – jantimon Commented May 5, 2017 at 16:55
-
Do you want the current state of the of
my-input
shared by themy-element
s? This might be less hacky. jsfiddle/9ukmy0k0/2 – Bert Commented May 5, 2017 at 18:01
2 Answers
Reset to default 3After further investigation I reached out to the VueJs team and got the feedback that the following approach could be a valid solution:
/**
* 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);
}
}
You can try it in the following fiddle
Generally when I hear questions like this, they seem to always be resolved by using some of Vue's more intimate and obscured inner beauty :)
I have used quite a few third party libs that 'insist on owning the data', which they use to modify the DOM - but if you can use these events, you can proxy the changes to a Vue owned object - or, if you can't have a vue-owned object, you can observe an independent data structure through puted properties.
window.someObjectINeedtoObserve = {...}
yourLib.on('someEvent', (data) => {
// affect someObjectINeedtoObserve...
})
new Vue ({
// ...
puted: {
myObject () {
// object now observed and bound and the dom will react to changes
return window.someObjectINeedtoObserve
}
}
})
If you could clarify the use case and libraries, we might be able to help more.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745523138a4631352.html
评论列表(0条)