web-dev-qa-db-fra.com

VueJs: liaison d'entrée Textarea

J'essaie de comprendre comment détecter le changement de la valeur sur la zone de texte à partir du composant.

Pour la saisie, nous pouvons simplement utiliser

<input
  :value="value"
  @input="update($event.target.value)"
>

Cependant sur textarea cela ne fonctionnera pas.

Je travaille avec le composant CKEditor, qui devrait mettre à jour le contenu de wysiwyg lorsque la valeur du modèle du composant parent (attaché à ce composant enfant) est mise à jour.

Mon composant Editor ressemble actuellement à ceci:

<template>
    <div class="editor" :class="groupCss">
        <textarea :id="id" v-model="input"></textarea>
    </div>
</template>

<script>
    export default {
        props: {
            value: {
                type: String,
                default: ''
            },
            id: {
                type: String,
                required: false,
                default: 'editor'
            }
        },
        data() {
            return {
                input: this.$slots.default ? this.$slots.default[0].text : '',
                config: {
                    ...
                }
            }
        },
        watch: {
            input(value) {
                this.update(value);
            }
        },
        methods: {
            update(value) {
                CKEDITOR.instances[this.id].setData(value);
            },
            fire(value) {
                this.$emit('input', value);
            }
        },
        mounted () {
            CKEDITOR.replace(this.id, this.config);
            CKEDITOR.instances[this.id].setData(this.input);
            this.fire(this.input);
            CKEDITOR.instances[this.id].on('change', () => {
                this.fire(CKEDITOR.instances[this.id].getData());
            });
        },
        destroyed () {
            if (CKEDITOR.instances[this.id]) {
                CKEDITOR.instances[this.id].destroy()
            }
        }
    }
</script>

et je l'inclus dans le composant parent

<html-editor
    v-model="fields.body"
    id="body"
></html-editor>

cependant, chaque fois que la valeur du modèle du composant parent change - cela ne déclenche pas l'observateur - ne met pas à jour la fenêtre de l'éditeur.

J'ai seulement besoin que la méthode update() soit appelée lorsque le modèle du composant parent fields.body Est mis à jour.

Un pointeur sur la façon dont je pourrais l'approcher?

6
Sebastian Sulinski

C'est un peu de code à déchiffrer, mais ce que je ferais serait de décomposer la zone de texte et la fenêtre HTML WYSIWYG en deux composants distincts, puis de faire synchroniser les valeurs par le parent, donc:

Composant TextArea:

<template id="editor">
  <textarea :value="value" @input="$emit('input', $event.target.value)" rows="10" cols="50"></textarea>
</template>

/**
 *  Editor TextArea
 */
Vue.component('editor', {
  template: '#editor',
  props: {
    value: {
      default: '',
      type: String
    }
  }
});

Tout ce que je fais ici est de renvoyer l'entrée au parent lorsqu'elle change, j'utilise l'entrée comme nom d'événement et value comme accessoire pour pouvoir utiliser v-model sur l'éditeur. Maintenant, j'ai juste besoin d'une fenêtre wysiwyg pour afficher le code:

Fenêtre WYSIWYG:

/**
 * WYSIWYG window
 */
Vue.component('wysiwyg', {
  template: `<div v-html="html"></div>`,
  props: {
    html: {
      default: '',
      type: String
    }
  }
}); 

Il ne se passe pas grand-chose, il rend simplement le code HTML qui est passé comme accessoire.

Enfin j'ai juste besoin de synchroniser les valeurs entre les composants:

<div id="app">
  <wysiwyg :html="value"></wysiwyg>
  <editor v-model="value"></editor>
</div>

new Vue({
  el: '#app',
  data: {
    value: '<b>Hello World</b>'
  }
})

Maintenant, lorsque l'éditeur change, il renvoie l'événement au parent, qui met à jour value et déclenche à son tour ce changement dans la fenêtre wysiwyg. Voici le tout en action: https://jsfiddle.net/Lnpmbpcr/

1
craig_h