javascript - VueJs manipulate inline template and reinitialize it - Stack Overflow

this question is similar to VueJS re-pile HTML in an inline-template ponent and also to How to make Vue

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 the my-elements? This might be less hacky. jsfiddle/9ukmy0k0/2 – Bert Commented May 5, 2017 at 18:01
 |  Show 1 more ment

2 Answers 2

Reset to default 3

After 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信