Vue组件中的jQuery插件:无法将值传递给prop

Posted

技术标签:

【中文标题】Vue组件中的jQuery插件:无法将值传递给prop【英文标题】:jQuery plugin in Vue component: Cannot pass value to prop 【发布时间】:2017-08-19 12:10:42 【问题描述】:

我在一个 vue 组件中添加了 jquery redactor 插件。该插件工作正常,但我需要访问 html 以便在 Vue 中看到它。

我已经尝试了所有我能想到的方法、计算属性,但我找不到方法。这特别棘手,因为 Redactor 将新的 html 添加到 dom 中,我需要从添加的 html 中获取数据。

目前我收到此错误,this.$emit is not a function。我需要将.redactor-editor 的 html 值放入 prop 中,以便在 vue 数据中可用。 var textContent 在控制台中正确打印,但我无法在 prop 中显示。非常感谢任何帮助。

组件

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

【问题讨论】:

不要将 prop 和计算的名称命名为相同的名称。我希望这是您的this.$emit 不是功能问题的原因。 为什么不直接指定数据值并使用它而不是道具?这似乎是一个内部值,而不是一个属性。 谢谢我改了,但没有效果 德普。我错过了回调。您需要正确调用您的函数。我会添加一个答案。 我尝试使用道具,而您在另一个问题上所做的 internalValue 方法在这里不起作用,因为编辑器将新 HTML 添加到 dom 中,所以我不能在模板中使用事件,因为html 不存在于模板中。这就是为什么我试图通过计算属性获取 HTML 并将其发送到道具。 【参考方案1】:

this.$emit is not a function 问题是因为this 指向window

我还将keyup 定义移到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));
    
;

【讨论】:

你的作品一如既往的精彩。谢谢大佬!!!我不知道在函数内部使用bind 嗯,有很多方法可以使用正确的this,这只是其中一种。请参阅本文档。 ***.com/documentation/vue.js/9350/… 你想在这个组件上使用v-model 吗?你想这样$emitredactorValue吗? 我想走 v-model 路线但后来我找不到方法,因为我需要把它放在上面的 html 不在模板中。顺便说一句,自从您将答案更新为使用 refsel 后,它已停止工作 我会支持这些。理想情况下,您希望使用这些而不是 jQuery。我只是没有什么东西可以玩来确保它有效。【参考方案2】:

只是为了添加到@BertEvans 的绝妙答案。这是一个将 props 和 v-model 重新添加到组合中的解决方案。这使您可以将编辑器内容作为值获取,并可以访问根目录中的数据。

组件

<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】:

这是我使用 Imperavi 的 Redactor Editor 3 工作的 VueJS 2 组件。 支持同一视图中的多编辑器,但编辑器需要唯一的名称/ID。 不需要 jQuery 库。

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 用法

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

使用 vee-validate 的自定义验证器示例:https://gist.github.com/matinfo/52214f7f34ce6b746b483f0f92e6b5e5

【讨论】:

【参考方案4】:

任何人都想以其他方式举办活动

即使你想使用 $emit 还有另一种方法是使用 EventBus 只需创建一个 event-bus.js 文件并编写此文件

import Vue from 'vue';
const EventBus  = new Vue();
export default EventBus;

在你的组件中导入之后

import EventBus from '/your path/event-bus.js';

然后你可以发射它

EventBus.emit('myevent','I am boy');

要接收它,您不必在接收组件属性时指定事件名称

你可以这样做

EventBus.on('myevent',value=>
console.log(value) // I am boy will be displayed
)

【讨论】:

以上是关于Vue组件中的jQuery插件:无法将值传递给prop的主要内容,如果未能解决你的问题,请参考以下文章

无法将 Laravel 刀片文件中的道具传递给 Vue 组件

如何将值从 Laravel 刀片传递给 vue 组件?

将对象数组传递给 Vue 规范中的数据对象

如何从rails中的视图将值传递给jquery?

无法正确地将值从父母传递给孩子和孩子传递给父母

通过jQuery ajax调用将值列表传递给django视图