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

时间:2019-01-31 20:56:02

标签: javascript vue.js

我有一个正在工作的Vue实例,但是现在我试图将其重构为我正在处理的项目的组件。我是Vue的新手,所以对我来说这都是学习。

这是密码笔https://codepen.io/qinglu/pen/mOKgPP?editors=1010上的代码链接

到目前为止,这是我凭自己的能力就能将其变成

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];
            });
        }
    }
};

1 个答案:

答案 0 :(得分:0)

因此,关于执行此操作的最佳方法还有很多话要说,但是基本上,您希望将props传递到您的tinyMce组件中,然后让您在父级上发出“ input”事件的侦听器,在哪里可以做点什么。我建议尝试Vue Single File Components以获得清晰性和可重用性。

甚至还有live example关于如何从Vue文档中导入和“组件化”应用的信息。

我已经通过在JS中创建一个称为“ mce-parent”的父组件来演示了这一点,该组件接收道具并将它们通过自身向下传递到tinyMce组件中。在“ parent-mce”组件中,您将看到@input的缩写,它是v-on:input的简称,它捕获了您正在发出的事件并将其发送到作用域方法doSomething()。我已经在https://codepen.io/anon/pen/OdmZOV?editors=1010

处修改了您的示例

这是代码:

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

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);
      }
    }
  }
});

父-母组件

// 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();
  }
};

主Vue应用入口点


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