2017-05-05 14 views
12

kwestia ta jest podobna do VueJS re-compile HTML in an inline-template component a także How to make Vue js directive working in an appended html elementVueJs manipulować szablon inline i ponownie zainicjować to

Niestety rozwiązanie w tej kwestii nie może być stosowany już dla bieżącej realizacji VueJS jako $compile został usunięty.

Moje przypadek użycia jest następujący:

muszę użyć kodu osobie trzeciej, która manipuluje stronę i pożary zdarzenie później. Teraz po wystrzeleniu tego wydarzenia chciałbym poinformować VueJS o tym, że powinien on ponownie zainicjować bieżący DOM.

(Osoba trzecia, która jest napisany w czystym JavaScript pozwala użytkownikowi na dodanie nowych elementów interfejsu na stronie)

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

Czy nowy kod może pojawić się w dowolnym miejscu na stronie? –

+0

Tak, istnieje wiele lokalizacji, które są generowane dynamicznie. Znalazłem rozwiązanie, ale wygląda to bardziej jak włamanie: https://jsfiddle.net/9ukmy0k0/ – jantimon

+1

Hackiness jest nieunikniony: naruszasz umowę z Vue, że będzie kontrolować DOM. –

Odpowiedz

2

Po dalszych badaniach sięgnąłem do VueJs te jestem i dostał feedback że następujące podejście mogłoby być poprawnym rozwiązaniem:

/** 
* 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); 
    } 
} 

Można spróbować go w następujący fiddle

1

Generalnie, gdy słyszę takie pytania, wydaje się, aby zawsze być rozwiązane za pomocą niektóre z bardziej intymnych i ukrytych wewnętrznych zalet Vue :)

Użyłem wielu bibliotek stron trzecich, które "domagają się posiadania danych", których używają do modyfikacji DOM - ale jeśli możesz użyć tych wydarzeń, może przekazywać zmiany do obiektu należącego do Vue - lub, jeśli nie możesz mieć obiektu będącego własnością Vue, możesz obserwuj niezależną strukturę danych za pomocą obliczonych właściwości.

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 
    } 
    } 
}) 

Jeśli możesz wyjaśnić przypadek użycia i biblioteki, możemy być w stanie pomóc więcej.

+0

Aby wyjaśnić, jeśli potrafisz wyrazić ogólne wymagania funkcjonalne, możesz uzyskać bardziej zwięzła odpowiedź niż twoje "obejście" powyżej - w ciągu moich 3 lat pracy z Vue, nigdy nie musiałem tego robić. Naprawdę myślę, że odpowiedź mogłaby polegać na przyjęciu innego podejścia do łączenia danych, domeny, instancja vue i Twoja trzecia strona lib. –

+0

Kluczowym problemem jest to, że nie budujemy tylko prostej aplikacji, ale staramy się używać Vue razem z CMS – jantimon

Powiązane problemy