O Vue.js monta o componente após a mutação na árvore do DOM para adicionar um componente do vue
Eu tenho um caso de uso (abaixo) em que precisomount
(se esse for o termo correto) um modelo de componente Vue.js que foi inserido no DOM via jQuery, eu posso configurar um Observador de Mutações ou reagir a determinados eventos que são acionados quando a mutação ocorre.
Estou usando o Vue.js v2
Aqui está um exemplo simples que reuni para ilustrar o ponto:
live jsFiddlehttps://jsfiddle.net/w7q7b1bh/2/
O HTML abaixo contéminlined-templates
para dois componentes
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="app">
<!-- The use of inline-template is required for my solution to work -->
<simple-counter inline-template>
<button v-bind:style="style" v-on:click="add">clicks: {{ counter }}</button>
</simple-counter>
<simple-counter inline-template>
<button v-on:click="counter += 1">{{ counter }}</button>
</simple-counter>
</div>
<button id="mutate">Mutate</button>
Os js:
// simple counter component
Vue.component('simple-counter', {
data: function() {
return {
counter: 0,
style: {
color: 'red',
width: '200px'
}
}
},
methods: {
add: function() {
this.counter = this.counter + 1;
this.style.color = this.style.color == 'red' ? 'green' : 'red';
}
}
})
// create the Vue instance
var initV = () => new Vue({
el: '#app'
});
// expose the instance for later use
window.v = initV();
// click handler that will add a new `simple-counter` template to the Vue.el scope
$('#mutate').click(function(){
$('#app').append(` <div is="simple-counter" inline-template>
<button v-bind:style="style" v-on:click="add">click to add: <span class="inactive" v-bind:class="{ active: true }">{{ counter }}</span></button></div>`)
// do something after the template is incerted
window.v.$destroy()
window.v = initV(); // does not work
})
Como mencionado no código, destruir a re-instanciação da instância do Vue não funciona. Entendo por que os modelos dos componentes são alterados na primeira instanciação do Vue para o HTML final. Quando você tenta instanciar uma segunda vez, os modelos não são lá, os componentes não sãomounted
Gostaria de encontrar os componentes recém-adicionados após a mutação e montar apenas esses, isso é possível? e como?
ATUALIZAR: Consegui encontrar uma maneira de fazer isso instanciando uma nova instância do Vue com el definido para a parte mutada específica do DOM em oposição a todo#app
árvore:
$('#mutate').click(function(){
var appended =
$(`
<div is="simple-counter" inline-template>
<button v-bind:style="style" v-on:click="add">
click to add: {{ counter }}
</button>
</div>`
).appendTo($('#app'));
var newV = new Vue({el: appended[0]});
});
Parece funcionar, mas também parece feio e não tenho certeza de que outras implicações isso possa ter ..
Caso de uso:
Estou trabalhando em uma maneira de escrever componentes Vue.js para um CMS chamado Adobe Experience Manager (AEM).
Eu escrevo meus componentes usandoinlined-template
o que me dá a vantagem do SEO e da renderização no servidor usando outra linguagem de modelo chamada HTL.
A maneira como a autoria do AEM funciona é que, quando um componente é editado (por meio de um diálogo), esse componente específico é renderizado novamente no lado do servidor e injetado de volta no DOM para substituir o componente antigo, tudo feito via Ajax e jQuery ( sem atualização do navegador).
Aqui está um exemplo
Modelo de componente AEM:<button>${properties.buttonTitle}</button>
Aqui está o que um autor pode fazer:
autor visita a página de autoriaabre a caixa de diálogo do componente do botão para editaraltera o buttonTitle para "new button title"Economizarao salvar, um ajax é enviado, o HTML do componente é renderizado novamente no servidor e retornado é o novo HTML. Agora, o HTML substitui o antigo HTML via jQuery (modifica o DOM)
Isso é bom para componentes estáticos, mas se esse era um componente do Vue.js., como montá-lo dinamicamente, mantendo outros componentes montados.
Uma solução fácil para isso é atualizar a página ... mas isso é apenas uma experiência ruim ... Tem que haver uma maneira melhor.