Ryan Shang

生死看淡,不服就干

0%

小程序调研报告

一、目的

结合团队现阶段技术栈,找到目前最适合团队快速上手小程序的技术栈。

二、框架

1. 现有框架对比

1 小程序 wepy mpvue megalo Taro
语法规范 小程序规范 类Vue规范 Vue规范 Vue规范 React规范
模板系统 字符串模板 字符串模板 字符串模板 字符串模板 JSX
类型系统 不支持 业务代码 业务代码 业务代码 业务代码 + JSX模板
组件规范 小程序组件 小程序组件 html标签 + 小程序组件 html标签 + 小程序组件 小程序组件
样式规范 wxss sass, less, stylus sass, less, postcss sass, less, postcss
组件化 小程序组件化 自定义组件化 Vue组件化规范 Vue组件化规范 React组件化规范
多端复用 复用为H5 复用为H5,将通过Weex支持移动端 复用为H5 复用为H5,将通过RN支持移动端
自动构建 内建构件系统 Webpack构建 内建构建系统 + Webpack构建 内建构建系统 + Webpack构建
上手成本 全新学习 熟悉Vue + wepy 熟悉Vue 熟悉Vue 熟悉React
数据流管理 Redux Vuex Vuex Redux

2. mpvue和megalo对比

(1) 不同点对比
1 mpvue megalo
vue语法支持程度 大部分vue语法 mpvue基础上,多支持filter,v-html,slot-scope,复杂差值表达式
单页面结构 vue页面文件、小程序配置文件、js文件 vue页面文件、js文件(配置文件放在vue页面文件中)
新增页面操作 修改app.json 修改app.json + 修改webpack配置
文档详细程度 起步早,相对丰富 起步晚,文档简单
(2) 试用megalo 出现问题(后期更新可能解决)
  1. megalo iconPath要用相对定位,否则报错

    1
    2
    3
    4
    5
    6
    7
    // index.js
    {
    "pagePath": "pages/index/index",
    "text": "首页",
    "iconPath": "../static/2018-12-10-小程序调研报告/index.png",
    "selectedIconPath": "../static/2018-12-10-小程序调研报告/index-active.png"
    }
  2. megalo pages可以用^标志首页,但增加页面需要改webpack entry

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // webpack.base.config.js
    entry: {
    'app': _.resolve( 'src/index.js' ),
    'pages/index/index': _.resolve( 'src/pages/index/index.js' ),
    'pages/logs/index': _.resolve( 'src/pages/logs/index.js' ),
    'pages/create/index': _.resolve( 'src/pages/create/index.js' ),
    'pages/table/index': _.resolve( 'src/pages/table/index.js' ),
    'pages/record/index': _.resolve( 'src/pages/record/index.js' ),
    }
  3. megalo没有自己的vue-cli模板,初始化项目比较麻烦

  4. megalo每个页面的vue文件需要设置mpType: ‘page’

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // index.vue
    export default {
    mpType: 'page',
    data () {
    return {
    motto: 'Hello World',
    userInfo: {}
    }
    }
    }
  5. megalo用小程序开发工具指向的是dist,个人感觉有时报错需要重启小程序开发工具或者删除dist重新打包才能解决

  6. 用官方megalo-demo,项目可以跑起来,新增页面无问题,但无法引第三方ui库,引用静态资源无法打包到dist中(因时间原因,无法具体研究webpack配置需要怎么写)

  7. 使用vue-cli初始化项目,根据官网文档修改webpack配置后编译,框架需要的一个包直接报错(因时间原因,不再具体研究)

三、UI库

1. 不能使用常见前端移动端UI库的原因

小程序架构如图:

小程序系统架构

整个小程序由两个 webview 组成,代码分为 UI 层和逻辑层。UI 层运行在第一个 WebView 当中,执行 DOM 操作和交互事件的响应,里面是 WAWebview.js 代码及编译后的内容。逻辑层执行在(第二个webview 中)独立的 JS 引擎中(iOS:JavaScriptCore, android:X5 JS解析器;统称 JSCore;开发工具中,nwjs Chrome 内核),WAService.js 代码和业务逻辑。

当我们对 view 层进行事件操作后,会通过 WeixinJSBridge 将数据传递到 Native 系统层。Native 系统层决定是否要用 native 处理,然后丢给 逻辑层进行用户的逻辑代码处理。逻辑层处理完毕后会将数据通过 WeixinJSBridge 返给 View 层。View 渲染更新视图。

UI和逻辑分开,有两个好处,一个是并行处理避免js运行时间长导致ui卡顿加快首屏渲染,另一个是不支持DOM操作,完全数据驱动。

按照小程序官方文档说明,页面的脚本逻辑是在JsCore中运行,JsCore是一个没有窗口对象的环境,所以不能在脚本中使用window,也无法在脚本中操作组件。

2. 小程序常见UI库对比

WeUI iView WeApp Vant WeApp Wux WeApp MinUI
组件数量 20+ 30+ 30+ 60+ 30+
github star数 7.6k+ 2.8k+ 7.1k+ 2.3k+ 2.8k+
半年内open issue数 <10 190+ 10+ 10+ 20+
半年内closed issue数 <10 40+ 320+ 60+ <10
半年内版本更新次数 0 <10 20+ 10+ <10

数据截止2018年11月

经过测试,UI库组件在一般项目开发中性能差距不大,结合上表数据来看,Vant的开发人员是最活跃的,使用人数最多,可以作为选择。

3. mpvue引入UI库(vant/iview/wux)方式

(1) 下载组件库(download zip/git clone/npm)

获取ui库的dist文件夹并放入项目static中

(2) 更改配置

Webpack.base.config=>module=>rules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// webpack.base.config.js
{
test: /\.js$/,
include: [resolve('src'), resolve('test'), resolve('static/vant')],
use: [
'babel-loader',
{
loader: 'mpvue-loader',
options: {
checkMPEntry: true
}
},
]
}
(3) 引入组件

在要使用组件的页面文件夹下的main.json中(没有新建),引入组件

1
2
3
4
5
6
7
// main.json
{
"usingComponents": {
"v-button": "/static/vant/button/index",
"v-icon": "/static/vant/icon/index"
}
}
(4) 使用组件

在.vue文件中的template标签中直接使用,不需要import引入

四、采坑(mpvue + vant)

  1. 使用vant需要开启小程序ES6转ES5功能(右上角——详情),否则报错

    不开启ES6转ES5报错

  2. Notify和Dialog import引入需要相对路径,否则无法找到模块

  3. 使用ui框架,双向绑定需要自己绑定change事件,mpvue做了双向绑定,但是只针对于input

  4. radio和checkbox和cell-group嵌套使用,因无法获取component,无法按照vant官方文档操作,只能点击勾选的对号进行选择,或者自己封装onchange事件

    checkbox和van-cell配合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- html结构 -->
<v-checkbox-group
:value="tablePropList"
@change="handleChange">
<v-cell-group>
<v-cell
v-for="(item, index) in tablePropListData"
:key="index"
:title="item.label"
:data-prop="item.prop"
clickable
@click="handleCheckboxClick($event, item, index)">
<v-checkbox
:class="'checkbox-' + item.prop"
:name="item.prop">
</v-checkbox>
</v-cell>
</v-cell-group>
</v-checkbox-group>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// vant官网方法
handleCheckboxClick (e, item, index) {
// 无法获取checkbox
let { prop } = e.currentTarget.dataset
let checkbox = this.$root.$mp.page.selectComponent(`.checbox-${prop}`)
checkbox.toggle()
}

// 自己编写change事件触发的方法
handleCheckboxClick (e, item, index) {
let prop = item.prop
if (this.tablePropList.includes(prop)) {
let index = this.tablePropList.indexOf(prop)
this.tablePropList.splice(index, 1)
} else {
this.tablePropList.push(prop)
}
}
  1. 在mpvue中,page实例获取方式是this.$root.mp.page,在vue文件中的this指向vue实例

五、结论

现阶段结合自身情况,使用 mpvue + vant 是最合适的方案,vant组件满足不了需求的,需要自己封装业务组件。