jsoneditor二次封装实时预览json编辑器组件react版

目录
  • 前言
  • 设计思路
  • 正文
  • jsoneditor的使用
  • 结合react进行二次封装

前言

做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,vue或react等MVVM框架提倡组件化开发,这样一方面可以提高组件复用性和可扩展性,另一方面也带来了项目开发的灵活性和可维护,方便多人开发协作.接下来文章将介绍如何使用react,开发一个自定义json编辑器组件.我们这里使用了jsoneditor这个第三方库,官方地址: jsoneditor 通过实现一个json在线编辑器,来学习如何一步步封装自己的组件(不限于react,vue,原理类似).

你将学到:

  • react组件封装的基本思路
  • SOLID (面向对象设计)原则介绍
  • jsoneditor用法
  • 使用PropTypes做组件类型检查

设计思路

在介绍组件设计思路之前,有必要介绍一下著名的SOLID原则.

SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)是由罗伯特·C·马丁提出的面向对象编程和面向对象设计的五个基本原则。利用这些原则,程序员能更容易和高效的开发一个可维护和扩展的系统。 SOLID被典型的应用在测试驱动开发上,并且是敏捷开发以及自适应软件开发的基本原则的重要组成部分。

  • S 单一功能原则: 规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。所有它的服务都应该严密的和该功能保持一致。
  • O 开闭原则: 规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。遵循这种原则的代码在扩展时并不需要改变。
  • L 里氏替换原则: 派生类(子类)对象可以在程序中代替其基类(超类)对象,是对子类型的特别定义.
  • I 接口隔离原则: 指明应用或者对象应该不依赖于它不使用的方法。接口隔离原则(ISP)拆分非常庞大臃肿的接口成为更小的和更具体的接口,这样应用或对象只需要知道它们感兴趣的方法。这种缩小的接口也被称为角色接口。接口隔离原则(ISP)的目的是系统去耦合,从而容易重构,更改和重新部署。接口隔离原则是在SOLID (面向对象设计)中五个面向对象设计(OOD)的原则之一,类似于在GRASP (面向对象设计)中的高内聚性。
  • D 依赖反转原则: 是指一种特定的解耦 形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。

掌握好这5个原则将有利于我们开发出更优秀的组件,请默默记住.接下来我们来看看json编辑器的设计思路.

如上所示, 和任何一个输入框一样, 参考antd组件设计方式并兼容antd的form表单, 我们提供了onChange方法.(具体细节下文会详细介绍)

首先利用jsoneditor渲染的基本样式以及API,我们能实现一个基本可用的json编辑器,然后通过对外暴露的json和onChange属性进行数据双向绑定, 通过onError来监控异常或者输入的错误, 通过themeBgColor来修改默认的主题色,通过这几个接口,我们便能完全掌握一个组件的运行情况.

正文

接下来我们就正式开始我们的正文.由于本文的组件是基于react实现的,但是用在vue,angular上,基本模式同样适用.关键就是掌握好不同框架的生命周期.

在学习实现json编辑器组件之前,我们有必要了解一下jsoneditor这个第三方组件的用法与api.

jsoneditor的使用

  • 安装

我们先执行npm install安装我们的组件

npm install jsoneditor

其次手动引入样式文件

<link href="jsoneditor/dist/jsoneditor.min.css" rel="external nofollow"  rel="stylesheet" type="text/css">

这样,我们就能使用它的api了:

<div id="jsoneditor" style="width: 400px; height: 400px;"></div>
<script>
    // 创建编辑器
    var container = document.getElementById("jsoneditor");
    var editor = new JSONEditor(container);
    // 设置json数据
    function setJSON () {
        var json = {
            "Array": [1, 2, 3],
            "Boolean": true,
            "Null": null,
            "Number": 123,
            "Object": {"a": "b", "c": "d"},
            "String": "Hello World"
        };
        editor.set(json);
    }
    // 获取json数据
    function getJSON() {
        var json = editor.get();
        alert(JSON.stringify(json, null, 2));
    }
</script>

所以你可能看到如下界面:

为了能实现实时预览和编辑,光这样还远远不够,我们还需要进行额外的处理.我们需要用到jsoneditor其他的api和技巧.

结合react进行二次封装

基于以上谈论,我们很容易将编辑器封装成react组件, 我们只需要在componentDidMount生命周期里初始化实例即可.react代码可能是这样的:

import React, { PureComponent } from 'react'
import JSONEditor from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.css'
class JsonEditor extends PureComponent {
  initJsonEditor = () => {
    const options = {
      mode: 'code',
      history: true,
      onChange: this.onChange,
      onValidationError: this.onError
    };
    this.jsoneditor = new JSONEditor(this.container, options)
    this.jsoneditor.set(this.props.value)
  }
  componentDidMount () {
    this.initJsonEditor()
  }
  componentWillUnmount () {
    if (this.jsoneditor) {
      this.jsoneditor.destroy()
    }
  }
  render() {
    return <div className="jsoneditor-react-container" ref={elem => this.container = elem} />
  }
}
export default JsonEditor

至于options里的选项, 我们可以参考jsoneditor的API文档,里面写的很详细, 通过以上代码,我们便可以实现一个基本的react版的json编辑器组件.接下来我们来按照设计思路一步步实现可实时预览的json编辑器组件.

  • 实现预览和编辑视图

其实这一点很好实现,我们只需要实例化2个编辑器实例,一个用于预览,一个用于编辑就好了.

import React, { PureComponent } from 'react'
import JSONEditor from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.css'
class JsonEditor extends PureComponent {
  onChange = () => {
    let value = this.jsoneditor.get()
    this.viewJsoneditor.set(value)
  }
  initJsonEditor = () => {
    const options = {
      mode: 'code',
      history: true
    };
    this.jsoneditor = new JSONEditor(this.container, options)
    this.jsoneditor.set(this.props.value)
  }
  initViewJsonEditor = () => {
    const options = {
      mode: 'view'
    };
    this.viewJsoneditor = new JSONEditor(this.viewContainer, options)
    this.viewJsoneditor.set(this.props.value)
  }
  componentDidMount () {
    this.initJsonEditor()
    this.initViewJsonEditor()
  }
  componentDidUpdate() {
    if(this.jsoneditor) {
      this.jsoneditor.update(this.props.value)
      this.viewJsoneditor.update(this.props.value)
    }
  }
  render() {
    return (
      <div className="jsonEditWrap">
        <div className="jsoneditor-react-container" ref={elem => this.container = elem} />
        <div className="jsoneditor-react-container" ref={elem => this.viewContainer = elem} />
      </div>
    );
  }
}
export default JsonEditor

这样,我们便能实现一个初步的可实时预览的编辑器.可能效果长这样:

接近于成熟版,但是还有很多细节要处理.

  • 对外暴露属性和方法以支持不同场景的需要
import React, { PureComponent } from 'react'
import JSONEditor from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.css'
class JsonEditor extends PureComponent {
  // 监听输入值的变化
  onChange = () => {
    let value = this.jsoneditor.get()
    this.props.onChange && this.props.onChange(value)
    this.viewJsoneditor.set(value)
  }
  // 对外暴露获取编辑器的json数据
  getJson = () => {
    this.props.getJson && this.props.getJson(this.jsoneditor.get())
  }
  // 对外提交错误信息
  onError = (errArr) => {
    this.props.onError && this.props.onError(errArr)
  }
  initJsonEditor = () => {
    const options = {
      mode: 'code',
      history: true,
      onChange: this.onChange,
      onValidationError: this.onError
    };
    this.jsoneditor = new JSONEditor(this.container, options)
    this.jsoneditor.set(this.props.value)
  }
  initViewJsonEditor = () => {
    const options = {
      mode: 'view'
    };
    this.viewJsoneditor = new JSONEditor(this.viewContainer, options)
    this.viewJsoneditor.set(this.props.value)
  }
  componentDidMount () {
    this.initJsonEditor()
    this.initViewJsonEditor()
    // 设置主题色
    this.container.querySelector('.jsoneditor-menu').style.backgroundColor = this.props.themeBgColor
    this.container.querySelector('.jsoneditor').style.border = `thin solid ${this.props.themeBgColor}`
    this.viewContainer.querySelector('.jsoneditor-menu').style.backgroundColor = this.props.themeBgColor
    this.viewContainer.querySelector('.jsoneditor').style.border = `thin solid ${this.props.themeBgColor}`
  }
  componentDidUpdate() {
    if(this.jsoneditor) {
      this.jsoneditor.update(this.props.json)
      this.viewJsoneditor.update(this.props.json)
    }
  }
  render() {
    return (
      <div className="jsonEditWrap">
        <div className="jsoneditor-react-container" ref={elem => this.container = elem} />
        <div className="jsoneditor-react-container" ref={elem => this.viewContainer = elem} />
      </div>
    );
  }
}
export default JsonEditor

通过以上的过程,我们已经完成一大半工作了,剩下的细节和优化工作,比如组件卸载时如何卸载实例, 对组件进行类型检测等,我们继续完成以上问题.

  • 使用PropTypes进行类型检测以及在组件卸载时清除实例 类型检测时react内部支持的,安装react的时候会自动帮我们安装PropTypes,具体用法可参考官网地址propTypes文档,其次我们会在react的componentWillUnmount生命周期中清除编辑器的实例以释放内存.完整代码如下:
import React, { PureComponent } from 'react'
import JSONEditor from 'jsoneditor'
import PropTypes from 'prop-types'
import 'jsoneditor/dist/jsoneditor.css'
/**
 * JsonEditor
 * @param {object} json 用于绑定的json数据
 * @param {func} onChange 变化时的回调
 * @param {func} getJson 为外部提供回去json的方法
 * @param {func} onError 为外部提供json格式错误的回调
 * @param {string} themeBgColor 为外部暴露修改主题色
 */
class JsonEditor extends PureComponent {
  onChange = () => {
    let value = this.jsoneditor.get()
    this.props.onChange && this.props.onChange(value)
    this.viewJsoneditor.set(value)
  }
  getJson = () => {
    this.props.getJson && this.props.getJson(this.jsoneditor.get())
  }
  onError = (errArr) => {
    this.props.onError && this.props.onError(errArr)
  }
  initJsonEditor = () => {
    const options = {
      mode: 'code',
      history: true,
      onChange: this.onChange,
      onValidationError: this.onError
    };
    this.jsoneditor = new JSONEditor(this.container, options)
    this.jsoneditor.set(this.props.value)
  }
  initViewJsonEditor = () => {
    const options = {
      mode: 'view'
    };
    this.viewJsoneditor = new JSONEditor(this.viewContainer, options)
    this.viewJsoneditor.set(this.props.value)
  }
  componentDidMount () {
    this.initJsonEditor()
    this.initViewJsonEditor()
    // 设置主题色
    this.container.querySelector('.jsoneditor-menu').style.backgroundColor = this.props.themeBgColor
    this.container.querySelector('.jsoneditor').style.border = `thin solid ${this.props.themeBgColor}`
    this.viewContainer.querySelector('.jsoneditor-menu').style.backgroundColor = this.props.themeBgColor
    this.viewContainer.querySelector('.jsoneditor').style.border = `thin solid ${this.props.themeBgColor}`
  }
  componentWillUnmount () {
    if (this.jsoneditor) {
      this.jsoneditor.destroy()
      this.viewJsoneditor.destroy()
    }
  }
  componentDidUpdate() {
    if(this.jsoneditor) {
      this.jsoneditor.update(this.props.json)
      this.viewJsoneditor.update(this.props.json)
    }
  }
  render() {
    return (
      <div className="jsonEditWrap">
        <div className="jsoneditor-react-container" ref={elem => this.container = elem} />
        <div className="jsoneditor-react-container" ref={elem => this.viewContainer = elem} />
      </div>
    );
  }
}
JsonEditor.propTypes = {
  json: PropTypes.object,
  onChange: PropTypes.func,
  getJson: PropTypes.func,
  onError: PropTypes.func,
  themeBgColor: PropTypes.string
}
export default JsonEditor

由于组件严格遵守开闭原则,所以我们可以提供更加定制的功能在我们的json编辑器中,已实现不同项目的需求.对于组件开发的健壮性探讨,除了使用propTypes外还可以基于typescript开发,这样适合团队开发组件库或者复杂项目组件的追溯和查错.最终效果如下:

笔者已经将实现过的组件发布到npm上了,大家如果感兴趣可以直接用npm安装后使用,方式如下:

npm i @alex_xu/xui
// 导入xui
import {
  Button,
  Skeleton,
  Empty,
  Progress,
  Tag,
  Switch,
  Drawer,
  Badge,
  Alert
} from '@alex_xu/xui'

该组件库支持按需导入,我们只需要在项目里配置babel-plugin-import即可,具体配置如下:

// .babelrc
"plugins": [
  ["import", { "libraryName": "@alex_xu/xui", "style": true }]
]

npm库截图如下:

以上就是jsoneditor二次封装实时预览json编辑器组件react版的详细内容,更多关于jsoneditor二次封装json的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用Js获取、插入和更改FCKeditor编辑器里的内容

    之前在一个系统里使用了FCKeditor编辑器,由于项目需求需要在FCKeditor里添加一个自定义的按钮用于实现自己的需求 主要是在点击该按钮时删除或添加FCKeditor编辑器里的内容 其实是一个很简单的需求,本来以为在FCKeditor可以很容易的实现 在Google上搜索自定义按钮,插件开发,经过近二个小时的摸索最终还是没有实现不知是我太笨还是自定义插件太难啦 通过JS方式来处理 1.在页面中添加checkbox元素并绑定事件,选中该元素时将在FCKeditor内容里添加"{#book#

  • js获取UEditor富文本编辑器中的图片地址

    写之前在网上找了很多方法,最简单的思路应该是1.获取UEditor中的内容:2.将获取到的字符串转换成jquery对象:3.选择器找到img元素,获取src值. var content= UE.getEditor('details').getContent();//获取编辑器内容 var $div = document.createElement("div");//创建一个div元素对象 $div.innerHTML = content;//往div里填充html var $v = $

  • js制作xml在线编辑器实例

    目录 前言 在线XML编辑器的需求 技术预研 可视化编程 VSCODE插件 在线编辑器 最初形态:简单的在线XML编辑器 用CodeMirror做编辑器 学习XML,并提取出tags规则 进化形态:加载树形文件结构和全文件校验功能的在线XML编辑器 左侧文件树 全文件校验功能 非递归遍历树 IndexDB保存文件内容 究极进化形态:突破浏览器沙盒限制,实现对电脑本地文件的增删改 更多的功能与细节 不足与总结 前言 一年多没更新博客了,原因是疫情期间<骑马与砍杀2>发售,然后去写游戏MOD去了.

  • vue-json-editor json编辑器的使用

    目录 一.概述 二.vue-json-editor 使用 安装插件 使用 访问 三.bin-code-editor 安装模块 引入 一.概述 现有一个vue项目,需要一个json编辑器,能够格式化json数据,同时也支持编辑功能. vue-json-editor 插件就可以实现这个功能 二.vue-json-editor 使用 安装插件 npm install vue-json-editor --save 使用 test.vue <template> <div style="w

  • 纯 JS 实现的轻量化图片编辑器实例详解

    目录 介绍 一款纯 JS 实现的轻量化图片编辑器 Optimizer 框架特点 Optimizer 框架使用 启动 场景管理器 (Scene) 页面事件Event 鼠标事件 键盘事件 注册组件 Component 使用组件 总结 介绍 因为一些特点的工作场景, 写文章的需要每次处理一些图片, 在上面加说明文字, 或者加一些图形 刚开始使用 PPT 来处理, 一张张复制过去, 做一些边框阴影处理, 再加一些图形, 然后再导出来复制到需要的地方, 而且导出后的图片之后可能不会再使用了还要清理. 图片

  • js处理网页编辑器转义、去除转义、去除HTML标签的正则

    富文本编辑器生成的HTML标签,进行转义,然后写入数据库,防止脚本注入: function htmlEncode(value){ return $('<div/>').text(value).html(); } 1.从数据库拿出的转义后的HTML标签内容,先得去除转义,然后再去除HTML标签,是生成缩略文字. /*移除HTML标签代码*/ function removeHTMLTag(str) { str = str.replace(/<\/?[^>]*>/g,''); //

  • jsoneditor二次封装实时预览json编辑器组件react版

    目录 前言 设计思路 正文 jsoneditor的使用 结合react进行二次封装 前言 做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,vue或react等MVVM框架提倡组件化开发,这样一方面可以提高组件复用性和可扩展性,另一方面也带来了项目开发的灵活性和可维护,方便多人开发协作.接下来文章将介绍如何使用react,开发一个自定义json编辑器组件.我们这里使用了jsoneditor这个第三方库,官方地址: jsoneditor 通过实现

  • Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】

    本文实例讲述了Thinkphp5+plupload实现支持实时预览的图片上传功能.分享给大家供大家参考,具体如下: 今天和大家分享一个国外的图片上传插件,这个插件支持分片上传大文件.其中著名的七牛云平台的jssdk就使用了puupload插件,可见这个插件还是相当牛叉的. 这个插件不仅仅支持图片上传,还支持大多数文件的上传,例如视频文件,音频文件,word文件等等,而且大文件都采用分片上传的机制. Plupload有以下功能和特点: 1.拥有多种上传方式:HTML5.flash.silverli

  • Android UI实时预览和编写的各种技巧

    一.啰嗦 之前有读者反馈说,你搞这个所谓的最佳实践,每篇文章最后就给了一个库,感觉不是很高大上.其实,我在写这个系列之初就有想过这个问题.我的目的是:给出最实用的库来帮助我们开发,并且尽可能地说明这个库是如何编写的,希望让初创公司的程序员少写点给后人留坑的代码(想必大家对此深有体会). 我之前给出的库都是很简单基础的,基本是一看就懂(但足够精妙),如果以后的文章涉及到了复杂的库,我会专门附加一篇库的讲解文. 如果一个库的原理你知道,此外这个库很容易扩展和维护,而且它还用到了很多最佳实践的经验,你

  • laravel框架上传图片实现实时预览功能

    在laravel框架中上传图片并实时预览,其实并没有那么难,下面给大家展示一下: HTML代码: <img class="pic house-a" οnclick="houseImgOne(this)" name="house_img_one" id="house_img_one" src=""> <input type="file" name="house_

  • VSCode设置网页代码实时预览的实现

    一.设置描述 1.VSCode作为一款很不错的开发软件,相比DW更小巧,用来测试前端特别不错,那么我们平时开发网页发现只有写完代码,然后保存,接下来到浏览器中刷新查看效果,然后不停重复,我们发现很多时间就这样浪费到了这三个步骤上. 2.其实我们可以在VSCode中配置一个网页服务器,修改完代码之后只需要保存代码浏览器就可以实时预览 二.操作步骤 1.打开VScode,点击坐标工具栏的最后一个进入插件安装 2.如果没有显示左边的工具栏,也可以在View中找到Extensions进入插件安装 3.在

  • JS实现上传图片实时预览功能

    前段时间在网络上找的代码,修改了一部分用在了项目里.原博客地址找不到了,如果原作者看到的话留言我,将于第一时间删除. //js本地图片预览,兼容ie[6-9].火狐.Chrome17+.Opera11+.Maxthon3 function PreviewImage(fileObj) { //创建dom元素 var divPreviewId = 'divPreview_' + fileObj.name; var imgPreviewId = 'imgHeadPhoto_' + fileObj.na

  • Android camera实时预览 实时处理,人脸识别示例

    Android camera实时预览 实时处理,面部认证. 预览操作是网友共享的代码,我在继承SurfaceView 的CameraSurfaceView 中加入了帧监听事件,每次预览监听前五个数据帧,在处理做一个面部识别. 先看目录关系 自定义控件CameraSurfaceView.java 自定义接口方法CameraInterface.java CameraActivity预览界面. CameraSurfaceView.Java package com.centaur.camera.prev

  • js实现Select头像选择实时预览代码

    本文实例讲述了js实现Select头像选择实时预览代码.分享给大家供大家参考.具体如下: 这里演示js实现Select头像选择,实时预览效果,在留言或评论的时候,让用户简易的选择头像,以前最常见的方式是使用单选框,当然使用其它的形式也可以,比如今天这个Select,下拉选框选择头像,也是不错的体验. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-select-ico-pic-view-codes/ 具体代码如下: <!DOCTYPE ht

  • Qt 使用 canon edsdk 实现实时预览的示例代码

    概述 想要使用 canon 的 sdk 进行实时的一个预览,即 LiveView 功能. 前期准备 前期的一些相机的连接,可以参考我之前写的文章QT 使用 canon sdk 拍照并保存到本机 实时预览步骤 StartLiveView 声明一个变量来标志 m_isLiveView 来标识 liveview 是否开启. 将实时预览输出到 PC 上 device |= kEdsEvfOutputDevice_PC; // ----------------------------- void Main

  • React实时预览react-live源码解析

    目录 引言 源码解读 输入内容 Provider generateElement 其他组件 总结 引言 react-live 是一个 react 的实时编辑器,可直接编辑 react 代码,并实时预览.可以看下官方的预览图: 本文针对的源码版本 src ├── components │ ├── Editor │ │ └── index.js │ └── Live │ ├── LiveContext.js │ ├── LiveEditor.js │ ├── LiveError.js │ ├── L

随机推荐