jQuery plugin in Vue component: Cannot pass value

2020-02-06 16:20发布

I have added the jquery redactor plugin in a vue component. The plugin is working fine but I need to access the html so I can see it in Vue.

I have tried everything I can think of, methods, computed properties but I can't find a way. It's particularly tricky because Redactor adds new html into the dom, and I need to get the data from the added html.

Currently I am getting this error, this.$emit is not a function. I need to get the html value of .redactor-editor into the prop so it will be available in the vue data. The var textContent prints out correctly in console but I can't get that to show in the prop. Any help is greatly appreciated.

Component

<template>
  <div>
    <textarea class="form-control question-create-editor" id="question_description" placeholder="Go wild with all the details here - make image upload work" rows="3">
  </div>
</template>

<script>
  export default {
    props: ['redactorValue'],
    mounted: function(){
          $('#question-create-form .question-create-editor').redactor({
            imageUpload:'/urlGoesHereBro/',
            plugins: ['video', 'imagemanager', 'counter', 'limiter'],
            buttonsHide:['html', 'formatting', 'deleted', 'indent', 'outdent', 'alignment', 'horizontalrule']
          });
    },
    computed: {
      redactorValue: function(){
        $('#question-create-form .redactor-editor').on('keyup', function(){
          var textContent = $('#question-create-form .redactor-editor').html();
          console.log( 'textContent = ' + textContent );
          this.$emit('redactorValue', textContent);
        });
      }
    }
};

HTML

<vueredactor></vueredactor>

3条回答
冷血范
2楼-- · 2020-02-06 17:07

Just to add to @BertEvans superb answer. Here is a solution that adds props and v-model back into the mix. This allows you to get the redactor content as a value and have access to that data in the root.

Component

<template>
  <div>
    <textarea class="form-control question-create-editor" id="question_description" placeholder="Go wild with all the details here - make image upload work" rows="3">
  </div>
</template>

<script>
  export default {
      props: ['value'],
      data(){
          return {
              redactorValue: null
          }
      },
      mounted: function(){
            $('#question-create-form .question-create-editor').redactor({
              imageUpload:'/urlGoesHereBro/',
              plugins: ['video', 'imagemanager', 'counter', 'limiter'],
              buttonsHide:['html', 'formatting', 'deleted', 'indent', 'outdent', 'alignment', 'horizontalrule']
            });

            $('#question-create-form .redactor-editor').on('blur', function(){
                this.redactorValue = $('#question-create-form .redactor-editor').html();
                this.$emit('input', this.redactorValue);
            }.bind(this));
      }
  };
</script>

JS

Vue.component('vueredactor', require('./components/redactor.vue'));

var App = new Vue({
                el: '#app',
                data: {
                  redactorContent: null
                }
            });

HTML

<div id="app>
    <vueredactor v-model="redactorContent"></vueredactor>
</div>
查看更多
混吃等死
3楼-- · 2020-02-06 17:10

The this.$emit is not a function issue is because this is pointing to the window.

Also I moved the keyup definition into mounted.

export default {
    data(){
        return {
            redactorValue: null
        }
    },
    mounted: function(){
          $('#question-create-form .question-create-editor').redactor({
            imageUpload:'/urlGoesHereBro/',
            plugins: ['video', 'imagemanager', 'counter', 'limiter'],
            buttonsHide:['html', 'formatting', 'deleted', 'indent', 'outdent', 'alignment', 'horizontalrule']
          });

          $('#question-create-form .redactor-editor').on('keyup', function(){
              this.redactorValue = $('#question-create-form .redactor-editor').html();
          }.bind(this));
    }
};
查看更多
Juvenile、少年°
4楼-- · 2020-02-06 17:23

Here my working VueJS 2 component with Redactor Editor 3 from Imperavi. Support multi-editor in same view, but editor need unique name/id. Not require jQuery library.

RedactorEditor.vue

<template>
<div class="redactor">
    <textarea ref="redactorContainer" :id="id" :value="value"></textarea>
</div>
</template>
<script>
    import 'addons/redactor/css/redactor.css'
    import 'addons/redactor/redactor'
    //import 'addons/redactor/plugins/wordslimiter/wordslimiter'
    //import 'addons/redactor/plugins/beyondgrammar/beyondgrammar'

    export default {
        name: 'redactor-editor',
        props: {
            value: {
                required: true,
                twoWay: true
            },
            id: {
                type: String,
                default: 'editor'
            },
            minHeight: {
                type: String,
                default: '300px',
            },
            maxHeight: {
                type: String,
                default: '800px',
            },
            buttons: {
                type: Array,
                default: () => ['html', 'format', 'bold', 'italic', 'deleted', 'lists', 'link']
            },
            plugins: {
                type: Array,
                default: () => []
            },
            wordslimiter: {
                type: Number,
                default: 0
            },
            beyondgrammarSettings: {
                type: Object,
                default: null
            }
        },
        data () {
            return {
                propValue: this.value
            }
        },
        created () {
            this.isChanging = false;
            this.app = null;
        },
        mounted () {
            var me = this;
            this.app = $R(this.$refs.redactorContainer, {
                style: true,
                breakline: false,
                shortcodes: false,
                pasteClean: true,
                autoparseImages: false,
                autoparseVideo: false,
                multipleUpload: false,
                clipboardUpload: false,
                pasteLinkTarget: '_blank',
                placeholder: 'Write your text here ...',
                minHeight: this.minHeight,
                maxHeight: this.maxHeight,
                buttons: this.buttons,
                plugins: this.plugins,
                wordslimiter: this.wordslimiter,
                beyondgrammar: this.beyondgrammarSettings,
                callbacks: {
                    start: function() {
                        // set initial data
                        this.source.setCode(me.propValue);
                    },
                    blur: function (e) {
                        // keyup not work with last typed text, fix sync with v-model by using blur
                        if (!me.isChanging) {
                            me.isChanging = true;
                            var code = this.source.getCode()
                            me.propValue = (code === null || code.length === 0 ? null : code);
                            me.$emit('input', me.propValue);
                            me.$nextTick(function() {
                                me.isChanging = false;
                            });
                        }
                    }
                }
            })
        },
        destroyed () {
            this.app = $R(this.$refs.redactorContainer)
            if (this.app) {
                this.app.destroy()
            }
        }
    };
</script>

App.vue

import Vue from 'vue'
import RedactorEditor from './components/RedactorEditor.vue'

// app
const app = new Vue({
    el: '#my-app',
    data: {
       editorButtons: ['undo', 'redo', 'bold', 'italic', 'lists', 'link'],
       editorPlugins: [],
       beyondgrammarSettings: {}
       editorHTMLContent: '',
    },
    components: {
        RedactorEditor
    }
}

HTML usage

<redactor-editor
    v-model="editorHTMLContent"
    :text-value="editorHTMLContent"
    :id="'editor_1"
    :name="'editor_1"
    :plugins="editorPlugins"
    :buttons="editorButtons"
></redactor-editor>

Example with custom Validator using vee-validate: https://gist.github.com/matinfo/52214f7f34ce6b746b483f0f92e6b5e5

查看更多
登录 后发表回答