For cases where you need to run an external JavaScript, especially the ones that manipulate the DOM, it is recommended that you encapsulate the DOM into a component.
Another important point is that the properties and options passed to the component must be reactive, in which case you should study the component to study the best approach.
And finally, just as important when starting the external component or mounting the Vue component is to destroy the external component by destroying the Vue component.
Below is an example of how to make a Component for Editing and Creating a Record within a Modal.
Vue.component('edit-or-create', {
template: '#edit-or-create',
props: ['show', 'nome', 'email', 'titulo'],
data () {
return {
inner: {
nome: '',
email: ''
}
}
},
mounted () {
this.modal = M.Modal.init(this.$refs.modal);
this.checkShow();
},
beforeDestroy () {
this.modal.destroy()
},
watch: {
show () {
this.checkShow();
}
},
methods: {
checkShow () {
if (this.show) {
this.inner.nome = this.nome
this.inner.email = this.email
this.modal.open()
} else {
this.modal.close()
}
},
cancelar () {
this.$emit('update:show', false);
},
salvar () {
this.$emit('update:nome', this.inner.nome);
this.$emit('update:email', this.inner.email);
this.$emit('update:show', false);
this.$emit('salvar')
}
}
});
new Vue({
el: '#app',
data () {
return {
create: { show: false, nome: '', email: '' },
contatos: [{
edit: false, nome: 'Tobias Mesquita', email: '[email protected]'
}]
}
},
methods: {
created () {
this.contatos.push({ edit: false, nome: this.create.nome, email: this.create.email })
},
apagar (contato) {
var index = this.contatos.indexOf(contato)
this.contatos.splice(index, 1)
}
}
})
body {
padding: 5px;
}
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.js"></script>
<div id="app">
<button class="waves-effect waves-light btn-small" @click="create.show = true">
<i class="material-icons left">note_add</i>Novo
</button>
<edit-or-create
titulo="Novo Contato"
:show.sync="create.show"
:nome.sync="create.nome"
:email.sync="create.email"
@salvar="created">
</edit-or-create>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Editar</th>
</tr>
</thead>
<tbody>
<tr v-for="(contato, indice) in contatos">
<td>{{contato.nome}}</td>
<td>{{contato.email}}</td>
<td>
<button class="btn waves-effect waves-light btn-small" @click="contato.edit = true">
<i class="material-icons left">edit</i>Editar
</button>
<button class="btn waves-effect waves-light btn-small" @click="apagar(contato)">
<i class="material-icons left">delete</i>Delete
</button>
<edit-or-create
:titulo="'Editar ' + indice"
:show.sync="contato.edit"
:nome.sync="contato.nome"
:email.sync="contato.email">
</edit-or-create>
</td>
</tr>
</tbody>
</table>
</div>
<script type="text/x-template" id="edit-or-create">
<div ref="modal" class="modal">
<div class="modal-content">
<h4>{{titulo}}</h4>
<div>
<div class="row">
<div class="input-field col s12">
<input id="first_name" type="text" v-model="inner.nome">
<label for="first_name">Nome</label>
</div>
<div class="input-field col s12">
<input id="last_name" type="text" v-model="inner.email">
<label for="last_name">Email</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn waves-effect waves-light btn-small" @click="cancelar">
Cancelar
</button>
<button class="btn waves-effect waves-light btn-small" @click="salvar">
Salvar
</button>
</div>
</div>
</script>
However, the most recommended would be to implement a modal-only component, and use a slot for it's content.