微信小程序-组件化开发(上)

小程序对组件化的“支持”情况小程序对组件化的“支持”情况:

微信小程序(以下简称“小程序”,版本)虽然默认定义了很多有用的组件,但是在开发小程序过程中,往往需要自定义业务组件。
而小程序开发者文档中却未对自定义组件给出很好的解决方案或示例。

猜其原因可能有两方面:

  1. 从小程序开放的API来看,它去除了DOM和BOM,视图与数据层交互采用简单的单向数据绑定和事件绑的形式。可能其初衷是想降低开发难度和学习门槛,尽量减少概念。
  2. 小程序推出时间不到一年,这些功能可能还在完善中。

自定义组件的难点

微信的组件化,总体而言,目标就是把具有特定功能和样式的wxml、wxss、js(可选)文件抽取出来,以便不同页面之间进行复用。
我们从实现上来考虑是否可行:

  • wxss支持文件之间的引用,采用命名隔离的话应该可以支持组件化的需求。即把不同组件拆成不同的wxss,通过一致的命名与组件的试图、逻辑对应,同时组件样式选择器都挂载在跟样式下。使用时记得引用该wxss就好。当然预编译语言中所使用的变量、函数什么的就不要想了~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// tab component
-
|- tab.wxml
|- tab.js
|- tab.wxss 

// tab.wxss
.tab {
    ...
}
.tab .itme {
    ...
}
...
  • wxml也支持引用,两种方式:template和include。区别在于作用域。include相当于把代码拷贝到当前位置,与页面共享作用域,而import拥有自己的独立作用于,一般需要传入对应的参数。这么看似乎template更适合,可是template的事件绑定却仍是和父页面共享作用域,也就是说数据在template独立作用域中,事件绑定在页面内作用域,两者之间的相互引用就会变得相当尴尬,还不如include顺畅。
  • 小程序支持ES6,所以我们可以用ES6的模块管理方式来引入对应的js文件。
  • 因为json是针对于页面进行的配置,组件关心的是局部样式和逻辑,所以组件化的时候我们并不需要它。

因为我们采用了include的方式共享了作用域,在简单页面的情况这种方式也不会出现什么问题,如果变量名或事件名被占用的时候换一个就好了。
但是在页面引用多个组件的情况下如何保证它们之间不产生冲突?你可能想到了用老办法命名隔离,组件内部变量和事件添加组件前缀用来和其它组件区分。
OK,在组件名不重复的情况下这是可行的。但是如果一个组件要同时触发自身内部事件和父页面事件就不是这么简单了。
所以我们需要解决的一个关键问题是:组件如何隔离作用域,并暴露属性或接口(函数)给页面或其它组件?

组件化解决方案

第三方实现

我们在探索组件化实现方式时,有一个第三方模块wepy脱颖而出。star数量超过了1k,文档清晰简约。
看看它的主要功能:

  1. 将小程序开发模式转为MVVM方式
  2. 支持类Vue.js 2.x风格的组件开发,包括单文件组件,支持scss、pug等。
  3. 支持加载外部NPM包
  4. 使用babel编译,支持ES6/ES7特性

MVVM多用于web单页应用,而小程序明显不是单页应用,而且也不支持双数据绑定,转为MVVM方式更多只是习惯上的喜好,谈不上什么优点。
小程序也支持ES6特性(以前也支持ES7,不知道为什么新版本取消了),用ES6特性可以完成外部NPM包引用。

所以最吸引人的功能就是第二点:支持组件化。

拿到官方给的示例wepy-wechat-demo编译后对比源码和编译后的代码来探究其实现组件化的思路。

整个项目非常清晰简单,我们以index页面调用tab组件为例进行分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src目录
-
|- components
 - tab.wpy
 ...
|- pages
 - index.wpy
 ...
 
// dist目录
- dist
|- components
 - tab.wxss
 - tab.js
|- pages 
 - index.js
 - index.json
 - index.wxml
 - index.wxss

js文件用ES6编写,通过babel转成ES5形式,看起来比较费劲,不过幸好我们暂时也不需要分析它。打开index.wxss和tab.wxss可以看到组件样式的编写和引用方式如我们所料,通过微信的@import方式引入。

1
2
3
4
5
6
7
8
9
10
11
12
// dist/components/tab.wxss
.tab {
    ...
}
.tab .item {
   ... 
}
...

// dist/pages/index.wxss
@import "./../components/tab.wxss";
...

很奇怪,在编译好的components文件夹中只能看到组件命名的js和wxss文件,wxml文件消失了~
所以先来看看index.wxml中怎么体现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// dist/pages/index.wxml
<view class="tab">
    <view class="tab_item tab_message{{$tab$active == 0 ? ' active' : ''}}" bindtap="$tab$change" data-wepy-params-a="0">
        <image class="icon" src="../images/message{{$tab$active == 0 ? '_active' : ''}}.png"/>
        <text class="title">微信</text>
    </view>
    ...
</view>

// src/components/tab.wxml
<template>
    <view class="tab">
        <view class="tab_item tab_message{{active == 0 ? ' active' : ''}}" @tap="change(0)">
            <image class="icon" src="../images/message{{active == 0 ? '_active' : ''}}.png"></image>
            <text class="title">微信</text>
        </view>
        ...
    </view>
</template>

这段编译后的代码和tab.wxml源文件基本一致,发生改变的是数据绑定和事件绑定的地方,进行了重命名。
由此可以推断,是通过wepy的编译工具wepy-cli,把页面上的组件引用替换成了源码并通过修改变命名来隔离组件作用域避免冲突。
而这些重新修改的变量和事件如何起作用?
wepy的文档中提到组件支持回调和事件冒泡、事件下发,要支持这个特性除了按其要求的格式进行编写之外,还需要在js中引用一个叫wepy的模块,如

import wepy from 'wepy'

由此可以推断,wepy-cli编译的时候进行了模板替换和变量名(事件名)替换,然后wepy模块来处理替换后的事件调用以及组件之间的通信。

如果仔细翻阅文档会发现其对组件的支持非常接近Vue.js 2.x,比如computed、watcher属性。行文此处,给作者由衷地点个赞。

那么这种方式是否就是最理想的组件化方式,或者说这种方式有什么缺陷呢?

转载于:https://my.oschina.net/u/3396785/blog/1510235

wepy 是一个小程序组件开发框架。 组件 小程序支持js模块,但彼此独立,业务代码与交互事件仍需在页面处理。无法实现组件的松耦合与复用的效果。 例如模板A中绑定一个bindtap="myclick",模板B中同样绑定一样bindtap="myclick",那么就会影响同一个页面事件。对于数据同样如此。因此只有通过改变变量或者事件方法,或者给其加不同前缀才能实现绑定不同事件或者不同数据。当页面复杂之后就十分不利于开发维护。 因此wepy让小程序支持组件开发组件的所有业务与功能在组件本身实现,组件组件之间彼此隔离,上述例子在wepy的组件开发过程中,A组件只会影响到A绑定的myclick,B也如此。 wepy编译组件的过程如下: 组件引用 当页面或者组件需要引入子组件时,需要在页面或者script中的components给组件分配唯一id,并且在template中添加标签,如index.wpy。 页面和组件都可以引入子组件,引入若干组件后,如下图: Index页面引入A,B,C三个组件,同时组件A和B又有自己的子组件D,E,F,G,H。 项目目录结构 ├── dist                   微信开发者工具指定的目录 ├── node_modules            ├── src                    代码编写的目录 |   ├── components         组件文件夹(非完整页面) |   |   ├── com_a.wpy      可复用组件 a |   |   └── com_b.wpy      可复用组件 b |   ├── pages              页面文件夹(完整页面) |   |   ├── index.wpy      页面 index |   |   └── page.wpy       页面 page |   └── app.wpy            小程序配置项(全局样式配置、声明钩子等) └── package.json           package 配置 主要解决问题 开发模式转换 支持组件开发 支持加载外部 NPM 包 单文件模式,使得目录结构更加清晰 默认使用 babel 编译,支持 ES6/7 的一些新特性 针对原生 API 进行优 标签:wepy  小程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值