鲁班H5(开源可视化搭建系统) 核心实现原理

12,192 阅读5分钟

鲁班H5核心原理解析(开源版本的拖拽生成H5平台,类似易企秀、人人秀的可视化搭建系统)

鲁班H5是基于Vue2.0开发的,通过拖拽的形式,生成页面的工具,类似易企秀百度 H5 等工具的可视化搭建系统

相关地址

  1. GitHub:github.com/ly525/luban…
  2. Gitee:gitee.com/ly525/luban…

鲁班H5是什么?

鲁班H5是基于Vue2.0开发的,通过拖拽的形式,生成页面的工具,类似易企秀、百度 H5 等的可视化搭建系统

Github:github.com/ly525/luban…

核心原理解析

本文中提到的“H5”均指代“基于移动端传播的可交互(不限于播放影音,页面滑动,擦除,页内动画,表单收集等方式)的轻量网站”)。相当于微信上的PPT,主要用于品牌方传播和推广的载体 - 摘自一个Geek范的H5页面制作工具

要解决的问题

从实现原理来说,其实需要解决的就是以下几个问题:

需要有哪些可以编辑的元素?

文本、图片、形状、音频、链接等,二期以后会逐步增加更多的可编辑元素。

如何编辑元素?

通过点击或者上传的形式新增,通过拖拽来调整大小尺寸及位置,通过编辑面板来修改样式。同时,不同的元素将拥有不同的编辑面板,如文字类型,可以修改字体、颜色、大小、对齐方式等,而图片类型,则可以进行缩放、裁剪、圆角、阴影等调整。

如何编辑和预览动画效果?

动画效果将模仿其他产品,合并至编辑面板,并通过点击图标的形式,更换不同的入场动画,更换的同时,触发本动画的实际效果预览。另外也可以点击独立的预览按钮,可以对已经编辑完毕的页面进行预览。

如何实现与后台的数据交互?

按页和页内元素组合成一个json对象,附带音频信息传递至后台数据接口,读取时同样处理。

如何将数据转换成手机端网页(所谓H5页面)?

借助vue的createElement方法,将json 逐一解析成对应的组件,渲染即可。
使用slider插件实现上下或者左右翻页。

如何实现兼容手机端网页?

目前市面上,手动开发这类型网页,一般有两种兼容方式,即固定尺寸兼容及百分比兼容,我称之为主动兼容和被动兼容,区别主要是在与元素css的尺寸计算方式以及viewport的写法,这类型文章网上已经有不少,这里就不再敷述。而在本项目当中,最终选择的是两者相结合的方式来实现,原因在之后的文章中会提及。

以上内容部分摘录自来自:blog.csdn.net/tech_meizu/…


核心原理解析

将 JSON 转换成 H5

回到 Vue 官方文档中

相信阅读过 Vue JSX 文档 的同学对下面的代码应该不会陌生,可以直接访问 在线Demo 

// 以下代码来自:https://cn.vuejs.org/v2/guide/render-function.html#createElement-参数

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // An HTML tag name, component options, or async
  // function resolving to one of these. Required.
  'div',

  // {Object}
  // A data object corresponding to the attributes
  // you would use in a template. Optional.
  {
    // (see details in the next section below)
  },

  // {String | Array}
  // Children VNodes, built using `createElement()`,
  // or using strings to get 'text VNodes'. Optional.
  [
    'Some text comes first.',
    createElement('h1', 'A headline'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

抽象抽象再抽象

我们对上面的 demo 进行进一步的抽象:

  1. 移除注释
  2. 把 createElement(tagName || componentOptions, {data}, children) 对应到上面的代码中,把 children 部分单独抽象成一个数组
  3. 整理之后的代码如下:
// a component options demo:
const MyComponent = {
  props:['someProp'],
  render(h) { 
    return h('span', this.someProp)
  },
}

new Vue({
  el: '#app',
  // 这里的 render(createElement) 我们更常见的写法是:render(h) 
  // 关于这部分的解释,可以参见: https://segmentfault.com/q/1010000007130348?_ea=17466196
  render(createElement) {
    const pageJSON = [
      'Some text comes first.',
      createElement('h1', 'A headline'),
      createElement(MyComponent /** component options */, {
        props: {
          someProp: 'foobar'
        }
      })
    ]
    return h('div', {}, pageJSON)
  }
})


// 再抽象一步
new Vue({
  el: '#app',
  render(h) {
    const pageJSON = [
      {component: 'span', text: 'Some text comes first.'},
      {component: 'h1', text: 'A headline'},
      {component: 'MyComponent', data: {props: {someProp: 'foobar'}} }
    ]
    return h('div', {}, pageJSON.map(ele => {
      return h(ele.component, ele.text ? ele.text : ele.data)
    }))
  }
})


// 再抽象一步(哎,不对啊,作者,我咋感觉你这一步啥都没做啊😂,你说对了)
const PageJSON = [
  {component: 'span', text: 'Some text comes first.'},
  {component: 'h1', text: 'A headline'},
  {component: 'MyComponent', data: {props: {someProp: 'foobar'}} }
]
new Vue({
  el: '#app',
  render(h) {
    return h('div', {}, pageJSON.map(ele => {
      return h(ele.component, ele.text ? ele.text : ele.data)
    }))
  }
})

// 再抽象一步
const WorkJSON = {
	title: '我是作品标题',
    description: '我是作品描述',
    created_time: '2019-09-01',
    updated_time: '2019-09-01',
    pages: [
      	elements: [
          {component: 'span', text: 'Some text comes first.'},
          {component: 'h1', text: 'A headline'},
          {component: 'MyComponent', data: {props: {someProp: 'foobar'}} }
        ],
    ],
}
new Vue({
  el: '#app',
  render(h) {
    return h('div', {}, WorkJSON.pages[0].elements.map(ele => {
      return h(ele.component, ele.text ? ele.text : ele.data)
    }))
  }
})


相信到最后以这一步大家应该有些头绪了吧(要没有的话 😂😂😂,接着往下看吧)
其实鲁班H5的一个作品其实是一个就是一个大JSON(结构和上面的 WorkJSON 几乎一致)
这个大JSON 里面包含了很多页面(鲁班源码-Page),每个页面里面包含了很多元素(鲁班源码-Element)
最终这个JSON 会传给 render(h) 进行解析渲染
到这里,也就能解答这一小节的问题了:

  1. 鲁班H5 的核心原理是什么??
  2. 如何将数据转换成手机端网页(所谓H5页面)?
  3. JSON 转换成 H5??

完结撒花 🎉🎉🎉🎉🎉🎉🎉🎉