简体   繁体   English

如何将 Vue 实例重构为工作组件

[英]How to refactor a Vue instance into a working component

I have a single Vue instance that is working but now I am trying to refactor it into a component for a project I am working on.我有一个正在运行的 Vue 实例,但现在我正在尝试将它重构为我正在处理的项目的组件。 I am new to Vue so this is all learning for me.我是 Vue 的新手,所以这对我来说都是学习的。

This is a link to the code on a code pen https://codepen.io/qinglu/pen/mOKgPP?editors=1010这是代码笔上代码的链接https://codepen.io/qinglu/pen/mOKgPP?editors=1010

So far this is all I have been able to turn it into with my knowledge到目前为止,这就是我能用我的知识把它变成的所有东西

export default 
{
    name: "vue-tinymce",
    data() 
    {
        return {
            content: "test content",
            content1: "text1 content1",
            tinymceOptions: tinymceOptions
        }
    },
    mounted()
    {
        var vm = this,
        options = $.extend(true, {}, tinymceOptions); // use jquery temporary

        // make an deep copy of options;should not modify tinymceOptions
        options.selector  =undefined;
        options.target  =vm.$el; // use options.target instead of options.selector

        var oldSetup = options.setup || function() {};
        options.setup = function(editor) 
        {
            console.log("setup");

            //Decorate origin one
            oldSetup(editor);  

            // Bind keyup
            editor.on("keyup",function(e)
            {
                // update model value;
                var value=editor.getContent();

                // Dom to model,this was a problem,when input in editor ? it will focus in 
                // the first line first word;
                vm.$emit("input",value); // who receive this event?
            });

            editor.on("blur",function()
            {
                vm.allowSetContent=true;
            });

            editor.on("focus",function()
            {
                vm.allowSetContent=false;
            });
        };

        tinymce.init(options)
            .then(function(editors)
            {
                vm.editor=editors[0];
            });
        }
    }
};

So there's a lot to be said here about the best way to do this, but basically you want to pass props down into your tinyMce component, then have the listener for the 'input' event you're emitting on the parent, where it can do something.所以这里有很多关于做到这一点的最佳方法要说,但基本上你想将道具传递到你的 tinyMce 组件中,然后让你在父级上发出的“输入”事件的侦听器,它可以做一点事。 I'd recommended trying Vue Single File Components for clarity and reusability.为了清晰和可重用性,我建议尝试使用Vue 单文件组件

There's even a live example of how to import and "componentize" an app from the Vue docs.甚至还有一个如何从 Vue 文档导入和“组件化”应用程序的实时示例

I've demonstrated this by creating a parent component in the JS called "mce-parent" that receives props and passes them through itself down into the tinyMce component.我通过在 JS 中创建一个名为“mce-parent”的父组件来证明这一点,该组件接收道具并将它们通过自身传递到 tinyMce 组件中。 And in the 'parent-mce' component, you'll see @input which is shorthand for v-on:input that's capturing you're emit event and sending it to the scoped method doSomething() .在 'parent-mce' 组件中,您会看到@inputv-on:input的简写,它捕获您发出的事件并将其发送到作用域方法doSomething() I've modified you're example for you here https://codepen.io/anon/pen/OdmZOV?editors=1010我在这里修改了你的例子https://codepen.io/anon/pen/OdmZOV?editors=1010

and here's the code:这是代码:

html html

<div id="example">
  <input type="text" v-model="content" class="form-control" />

  
  <div class="row">
    <div class="col-md-6">
      <!-- Don't need to pass the MCE options,
      as they're in the mce-parent component -->
      <mce-parent :value="content"></mce-parent>
    </div>
    <div class="col-md-6">
  
    </div>
  </div>
</div> 

tinyMce component tinyMce 组件

export default Vue.component("vue-tinymce",{
  template:"<textarea>{{value}}</textarea>",
  props:["value","options"],
  mounted:function(){
    var vm=this,
       options=$.extend(true, {}, tinymceOptions); // use jquery temporary
    
    // make an deep copy of options;should not modify tinymceOptions
    options.selector=undefined;
    options.target=vm.$el; // use options.target instand of options.selector
    var oldSetup=options.setup||function(){};
    
    options.setup=function(editor){
      console.log("setup");
      
      //Decorate origni one
      oldSetup(editor);
      
      // Bind keyup
      editor.on("keyup",function(e){
        // update model value;
        var value=editor.getContent();
        // Dom to model,this was a problem,when input in editor ? it will focus in the first line first word;
        vm.$emit("input",value); // who recieve this event?
      });
      
      editor.on("blur",function(){
        vm.allowSetContent=true;
      });
      
      editor.on("focus",function(){
         vm.allowSetContent=false;
      })
    };
    
    tinymce.init(options).then(function(editors){
      vm.editor=editors[0];
    })
  },
  watch:{
    value:function(content)
    {
      if(this.editor&&this.allowSetContent)
      {
        // setContent will let editor focus in first line and first world
        this.editor.setContent(content);
      }
    }
  }
});

mce-parent component mce-父组件

// this is just an example
import tinyMce from './components/TinyMce.js';
Vue.component("mce-parent",{
  data : {
    return {
      tinymceOptions : tinymceOptions,
    }
  },
  template:`<div class='mce-parent'>`
              `<tiny-mce @input="doSomething" :value="value" :options="tinymceOptions"/>`
              `</tiny-mce>`
            `</div>`,
  props : ['value'],
  components : { 'tiny-mce' : tinyMce },
  methods : {
    doSomething(value){
      console.log(value)
    }
  }
});

var tinymceOptions={
  selector: 'textarea',
  height: 200,
  menubar: true,
  plugins: [
    'advlist autolink lists link image charmap print preview hr anchor pagebreak',
    'searchreplace wordcount visualblocks visualchars code fullscreen',
    'insertdatetime media nonbreaking save table contextmenu directionality',
    'emoticons template paste textcolor colorpicker textpattern imagetools codesample toc'
  ],
  toolbar1: 'undo redo | insert | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image',
  toolbar2: 'print preview media | forecolor backcolor emoticons | codesample',
  valid_elements:"*[*]",
  content_css: '//www.tinymce.com/css/codepen.min.css',
  images_upload_url: 'postAcceptor.php',
  images_upload_base_path: '/some/basepath',
  images_upload_credentials: true,
  images_upload_handler: function (blobInfo, success, failure) {
    var xhr, formData;
    xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', 'postAcceptor.php');
    xhr.onload = function() {
      var json;

      if (xhr.status != 200) {
        failure('HTTP Error: ' + xhr.status);
        return;
      }
      json = JSON.parse(xhr.responseText);

      if (!json || typeof json.location != 'string') {
        failure('Invalid JSON: ' + xhr.responseText);
        return;
      }
      success(json.location);
    };
    formData = new FormData();
    formData.append('file', blobInfo.blob(), fileName(blobInfo));
    xhr.send(formData);
  },
  image_title: true, 
  // enable automatic uploads of images represented by blob or data URIs
  automatic_uploads: true,
  // URL of our upload handler (for more details check: https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_url)
  images_upload_url: 'postAcceptor.php',
  // here we add custom filepicker only to Image dialog
  file_picker_types: 'image', 
  // and here's our custom image picker
  file_picker_callback: function(cb, value, meta) {
    var input = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('accept', 'image/*');
    
    // Note: In modern browsers input[type="file"] is functional without 
    // even adding it to the DOM, but that might not be the case in some older
    // or quirky browsers like IE, so you might want to add it to the DOM
    // just in case, and visually hide it. And do not forget do remove it
    // once you do not need it anymore.

    input.onchange = function() {
      var file = this.files[0];
      
      // Note: Now we need to register the blob in TinyMCEs image blob
      // registry. In the next release this part hopefully won't be
      // necessary, as we are looking to handle it internally.
      var id = 'blobid' + (new Date()).getTime();
      var blobCache = tinymce.activeEditor.editorUpload.blobCache;
      var blobInfo = blobCache.create(id, file);
      blobCache.add(blobInfo);
      
      // call the callback and populate the Title field with the file name
      cb(blobInfo.blobUri(), { title: file.name });
    };
    
    input.click();
  }
};

main Vue app entry point主 Vue 应用程序入口点


var vm=new Vue({
  el:"#example",
  data:{
    content:"test content",
    content1:"text1 content1"
   }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM