前言

前面我们研究了下微信小程序的执行流程,因为拿不到源码,只能算我们的猜想,我们需要更加了解小程序还需要做具体的项目,于是我们将原来那套还算复杂的业务拿出来:

【组件化开发】前端进阶篇之如何编写可维护可升级的代码(有些晦涩有些乱,但是对于整体了解小程序结构有帮助)

我们用小程序实现这里的代码,看看是个什么样的体验,另外我这里想保证代码最大程度重用,为后续一端代码四端运行做前驱探索。

页面复杂度还是比较高的,包括了:

① 弹出层

② 页面跳转

③ 缓存

④ 数据请求

⑤ 列表页、滚动分页

⑥ ......

我相信完成了这个例子,我们对小程序业务代码怎么写会有比较好的了解,于是让我们开始今天的代码吧。

小程序的布局

为什么不使用HTML&CSS

微信小程序这种平台型的超越Hybrid系统诞生还是有一些客观条件的,其中一个就是移动端的应用相对来说简单的多,想想PC负责的布局,如果要使用小程序实现,那么复杂度会提高很多。

小程序代码编写逻辑层依旧使用JS完成,但是结构层以及样式层推出了:

① WXML,Weixin Markup Language,是微信设计的一套标签语言,与HTML类似,做过React&Vue的同学会非常熟悉

② WXSS,WeiXin Style Sheets,是一套样式语言,用于定义样式,与CSS类似,一般认为是CSS的子集

因为小程序中UI组件都是Native实现,所以小程序直接手起刀落压根放弃让我们使用HTML容器,这样做我觉得有个好处是:

为了更好的限制,我之前也在做Hybrid乃至前端框架,一般来说我会限制到View级别的实习,要求必须按照我的规则做,但是因为入口为index.html文件,我甚至将全局控制器App的实例化放到了main.js里面,只提供了建议的做法,事实上HTML还是太过灵活,有些同事逐渐根本不按照我们的规则玩,他觉得他的做法更好,但是这样一来便会破坏了项目的总体性,后续的工程性的优化或者监控可能就不能帮助他了,从某个角度来说,我是认可小程序的做法的。

我们之前在这里研究过自定义标签的做法:从DOM操作看Vue&React的前端组件化,顺带补齐React的demo

 <article class="cm-page page-list" id="main">
<div class="js_sort_wrapper sort-bar-wrapper">
<mySortBar :entity="sortEntity"></mySortBar>
</div>
<myList :entity="listEntity" :sort="sort"></myList>
</article>

从这个文章以及小程序的实现可以看出基本的概念:

① 标签的出现根本不是做标签用,而是为了让JS捕捉执行相关逻辑,最后生成真正的标签

② 为了做更好的限制,小程序根本不提供入口index.html文件了,所以这里的标签是用作JS做模板解析后生成Native能识别的代码,更具体点说是,Native实现了一个组件,组件有很多规则,可以使用JS去调用,正如我们这里的header组件调用逻辑(JS会设置Native的Header组件展示),这里如果不太清晰可以参考下这个文章:浅谈Hybrid技术的设计与实现第二弹

当然,小程序底层具体是不是这么做,我们不得而知,如果有小程序的同事,可以指导下:),至此,我觉得可以从技术层面说明为什么不直接使用HTML&CSS了:更好的业务限制 + 方便JS解析模板被Native执行。

小程序组件

我们之前做Hybrid应用的时候,事实上只提供了一个真正具有结构的组件Header,其他loading类的提示组件都比较简单,而我们看看小程序提供了哪些组件呢:

容器类组件

view&scroll-view&swiper等作为容器组件存在,这里官方有基本介绍,我们这里看看其中一个即可:

这里官方给了一个demo进行说明:

 <view class="section">
<view class="section__title">flex-direction: row</view>
<view class="flex-wrp" style="flex-direction:row;">
<view class="flex-item bc_green">1</view>
<view class="flex-item bc_red">2</view>
<view class="flex-item bc_blue">3</view>
</view>
</view>
<view class="section">
<view class="section__title">flex-direction: column</view>
<view class="flex-wrp" style="height: 300px;flex-direction:column;">
<view class="flex-item bc_green">1</view>
<view class="flex-item bc_red">2</view>
<view class="flex-item bc_blue">3</view>
</view>
</view>
 @import "../lib/weui.wxss";

 .page-section{
margin-bottom: 20rpx;
}
.flex-wrp {display: flex;}
.bc_green {background: green;width:100px; height: 100px;}
.bc_red {background: red;width:100px; height: 100px;}
.bc_blue {background: blue;width:100px; height: 100px;}

可以将这个标签理解为div类组件。

swipe

一般来说,Native提供的轮播图体验要好得多,所以这里也提供了一个Native的组件:

 <view class="container">
<view class="page-body">
<view class="page-section page-section-spacing swiper">
<swiper
indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" circular="{{circular}}" vertical="{{vertical}}"
interval="{{interval}}" duration="{{duration}}" previous-margin="{{previousMargin}}px" next-margin="{{nextMargin}}px">
<block wx:for="{{background}}" wx:key="*this">
<swiper-item>
<view class="swiper-item {{item}}"></view>
</swiper-item>
</block>
</swiper>
</view>
<view class="page-section" style="margin-top: 40rpx;margin-bottom: 0;">
<view class="weui-cells weui-cells_after-title">
<view class="weui-cell weui-cell_switch">
<view class="weui-cell__bd">指示点</view>
<view class="weui-cell__ft">
<switch checked="{{indicatorDots}}" bindchange="changeProperty" data-property-name="indicatorDots" />
</view>
</view>
<view class="weui-cell weui-cell_switch">
<view class="weui-cell__bd">自动播放</view>
<view class="weui-cell__ft">
<switch checked="{{autoplay}}" bindchange="changeProperty" data-property-name="autoplay" />
</view>
</view>
<view class="weui-cell weui-cell_switch">
<view class="weui-cell__bd">衔接滑动</view>
<view class="weui-cell__ft">
<switch checked="{{circular}}" bindchange="changeProperty" data-property-name="circular" />
</view>
</view>
<view class="weui-cell weui-cell_switch">
<view class="weui-cell__bd">竖向</view>
<view class="weui-cell__ft">
<switch checked="{{vertical}}" bindchange="changeProperty" data-property-name="vertical" />
</view>
</view>
</view>
</view> <view class="page-section page-section-spacing">
<view class="page-section-title">
<text>幻灯片切换时长(ms)</text>
<text class="info">{{duration}}</text>
</view>
<slider value="{{duration}}" min="500" max="2000" bindchange="changeProperty" data-property-name="duration" />
<view class="page-section-title">
<text>自动播放间隔时长(ms)</text>
<text class="info">{{interval}}</text>
</view>
<slider value="{{interval}}" min="2000" max="10000" bindchange="changeProperty" data-property-name="interval" />
<view class="page-section-title">
<text>前边距(px)</text>
<text class="info">{{previousMargin}}</text>
</view>
<slider value="{{previousMargin}}" min="0" max="50" bindchange="changeProperty" data-property-name="previousMargin" />
<view class="page-section-title">
<text>后边距(px)</text>
<text class="info">{{nextMargin}}</text>
</view>
<slider value="{{nextMargin}}" min="0" max="50" bindchange="changeProperty" data-property-name="nextMargin" />
</view>
</view>
</view>
 Page({
data: {
background: ['demo-text-1', 'demo-text-2', 'demo-text-3'],
indicatorDots: true,
vertical: false,
autoplay: false,
circular: false,
interval: 2000,
duration: 500,
previousMargin: 0,
nextMargin: 0
},
changeProperty: function (e) {
var propertyName = e.currentTarget.dataset.propertyName
var newData = {}
newData[propertyName] = e.detail.value
this.setData(newData)
},
changeIndicatorDots: function (e) {
this.setData({
indicatorDots: !this.data.indicatorDots
})
},
changeAutoplay: function (e) {
this.setData({
autoplay: !this.data.autoplay
})
},
intervalChange: function (e) {
this.setData({
interval: e.detail.value
})
},
durationChange: function (e) {
this.setData({
duration: e.detail.value
})
}
})

有demo有代码,还是比较清晰。

movable-area

提供一个可以移动的区域,暂时没想到应用场景......

icon

图标,小程序这边还扩展了一下,给了很多默认的图标样式,能满足基本需求

text

文本

rich-text

富文本,用于展示文章,支持HTML,这里的nodes属性建议使用数组,类型,还不如系统自己解析js算了,因为不会有人像这样写代码(nodes看上去很蠢):

 Page({
data: {
html: '<div class="div_class" style="line-height: 60px; color: red;">Hello&nbsp;World!</div><script>console.log(1)</script>',
nodes: [{
name: 'div',
attrs: {
class: 'div_class',
style: 'line-height: 60px; color: red;'
},
children: [{
type: 'text',
text: 'Hello&nbsp;World!'
}]
}]
},
tap() {
console.log('tap')
}
})

progress

进度条

button

按钮

checkbox

选择框

form

表单相关

input

输入框,小程序的数据流动是单向的,每次数据更新,动态调用setData改变数据便会触发view更新,底层实现便不知道了;文本框值改变js需要自己去获取

label

与html一致,用以点击文字操作控件,主要用于文本框

picker&picker-view

用于级联操作

navigator&function-page-navigator

页面链接,这个组件感觉不利于跳转收口,建议少用

其他组件请大家直接到这里来看demo,非常清晰:

https://developers.weixin.qq.com/miniprogram/dev/component/map.html#map

总结

可以看出,小程序Native层是将常用的HTML标签分别都实现了一次,使用这些组件可以拼接处任何复杂的组件。至于样式方面,WXSS与CSS大同小异,其中主要区别是小程序没有使用px而是使用的rpx,这个类似于rem的实现,为了解决移动端的适配问题而存在,总而言之,你在iPhone6设计搞上是多少px就写成多少rpx就行,其余系统会帮你完成适配工作,这块透明做的很好,后续样式我们直接上实例即可。

小程序的生命周期

我们这里上一张图:

这张图不但真实反映了Page的生命周期,也将我们之前的猜想做了一个证明,解读这张图大概是这个意思(未必正确,如有错误请指出):

Native层在载入小程序时候,起了两个线程一个的view Thread一个是AppService Thread,我这边理解下来应该就是程序逻辑执行与页面渲染分离,也许是想优化性能,这里更具体一点的解释是(带有猜测了):微信会开一个webview来执行我们的JS逻辑,然后会开一个Native View UI执行页面渲染;两个部分是彼此独立的,页面点击时候触发事件,View线程会获取APPService服务线程(其实就是获取webview),执行其中的js逻辑;APPService执行js逻辑改变数据通过setData调用,触发一个JSCore通信,通知view线程执行UI更新,这里结合这张图做下理解:

① 微信打开一个小程序时,主UI线程继续运行,开启一个webview(我认为这里的主线程就是view Thread,webview就是APPService线程,这里可能有误)

② 主View等待构建页面命令,逻辑层开始载入js逻辑(编译过),微信底层应该会将WXML以及WXSS翻译为JS代码,逻辑层执行JS代码做一些初始化工作APP结束后,开始Page逻辑,而他这个图只有Page的逻辑,没有将app囊括进去,这里也引发了我一个疑惑:我在onLoad的时候打了个断点,而页面这个时候事实上已经进行了结构层的渲染,也就是说页面的WXML逻辑已经执行了:

如果要按照我现有的逻辑下做解释的话,我认为实例化Page的时候,执行了一个create事件,但是小程序并没有释放onCreate事件让我们做注册,所以我这里知识体系的基础依旧是:

JS逻辑先于Native UI 执行,页面渲染是由实例化Page时候发出

所以我觉得,这里的图好像少了一部分(或者说我理解是有问题的):

③ 业务线程执行实例化Page逻辑,引发onLoad、onShow事件,onShow的时候页面初步渲染已经结束,如果系统有异步数据或者其他再次数据渲染会执行setData,引发Native UI更新,逻辑结束

但是微信给出的图不可能是错的,而从图上看,首次异步通知是由View Thread发起的,我这里就很是困惑了

微信小程序开发02-小程序基本介绍的更多相关文章

  1. 微信小程序开发 -- 02

    微信小程序开发 --02 微信小程序在开发中,难度系数不是很大,其中应用的技术也是web开发中常用的技术,虽然在微信开发者工具中的叫法与常见的web开发的叫法不太一样. 首先,在微信小程序开发中,代码 ...

  2. 微信小程序开发 [02] 页面注册和基本组件

    1.页面注册 既然我们希望跳转到新的页面,那自然要新建页面相关的文件才行.在开篇已经讲过,一个小程序页面由四个文件组成,假如我们的页面名为welcome,那么这四个文件则是: welcome.js w ...

  3. 微信小程序开发 [01] 小程序基本结构和官方IDE简介

    1.小程序账户注册 实际上在进行开发时没有注册小程序账户也是可以的,官方提供的IDE提供实时编译模拟预览,和当前你有没有绑定小程序账户没有关系. 当然,最终你要正式上线你的小程序的话,肯定还是需要账户 ...

  4. 微信小程序开发教程(一)—介绍和准备

    前言: 因为客户需要,也为了更好的发展我们公司的产品,所以决定扩展移动端.但是由于公司没有原生安卓开发人员,而且开发安卓成本比较高,所以公司一致决定开发微信小程序,也是由于微信小程序最近的火热. 后台 ...

  5. 微信公众平台开发(84) 小i机器人

    很多朋友询问如何开发小黄鸡之类的智能聊天机器人,但遗憾的是小黄鸡接口申请页面在最近几个月里都无法访问,且使用时限制太大,我们找了另一个接口:小i机器人.本文介绍如何在微信公众平台中使用小i接口开发智能 ...

  6. 微信小程序开发——获取小程序带参二维码全流程

    前言: 想要获取微信小程序带参数二维码,如这种: 官方文档只说了获取小程序码和二维码的三种接口及调用(参考链接:https://developers.weixin.qq.com/miniprogram ...

  7. 微信小程序开发——修改小程序原生checkbox、radio默认样式

    复选框: 闲话少说,这里直接介绍如何修改小程序提供的复选框的样式,如原生的是这样的: 需要的是这样的: 示例代码: /*复选框外框样式*/ checkbox .wx-checkbox-input { ...

  8. WPF程序开发方法小总结

    1.先做静态界面(静态界面带有 示例 数据---> 展示布局效果) 2.然后在VM写完之后,再对静态界面绑定数据源属性

  9. php微信公众号开发入门小教程

    1.配置相关服务器 (1) 如下,把自己的服务器ip白名单配置上: (2) 开始配置令牌,配置令牌时先需要把现成的代码放到自己的服务器上面,代码里面包含自己的设置的令牌号码,这样才可以配置成功. 注意 ...

  10. 微信公众号开发 token 验证程序

    <?php traceHttp(); define("TOKEN", "gmll001"); $wechatObj = new wechatCallbac ...

随机推荐

  1. SQL基础操作汇总

    SQL基础操作汇总 一.表操作 1.表的创建(CREATE TABLE): 基本语句格式:    CREATE TABLE  table_name ( col_name    datatype, -- ...

  2. JS基础:常用API

    全局属性 typeof() 检测数据类型 parseInt() 从字符串解析一个整数 parseFloat() 从字符串解析一个小数 Number() 强制类型转换为数字 String() 强制类型转 ...

  3. cmd 【已解决】windows连接手机,运行adb devices提示“unauthorized”

    报错截图如下: 问题原因:电脑连接手机.手机未授权 解决方式: 设置----开发者选项-----打开USB调试,出现如下弹框,点击"确定"即可解决问题.

  4. 『zkw线段树及其简单运用』

    阅读本文前,请确保已经阅读并理解了如下两篇文章: 『线段树 Segment Tree』 『线段树简单运用』 引入 这是一种由\(THU-zkw\)大佬发明的数据结构,本质上是经典的线段树区间划分思想, ...

  5. Linux 文件/文件夹无法删除问题解决方案

    最近我们的服务器被黑客攻击,然后有些文件的属性被修改,导致我们无法删除病毒文件,同时采用 root 用户也无法删除,现在把解决方案记录下来. 普通删除 如果文件是当前用户的,那么使用 rm 命令就可以 ...

  6. CentOS7搭建本地YUM仓库,并定期同步阿里云源

    CentOS7同步阿里云镜像rpm包并自建本地yum仓库 系统环境 # cat /etc/centos-release CentOS Linux release 7.6.1810 (Core) # u ...

  7. 从壹开始 [vueAdmin后台] 之三 || 动态路由配置 & 项目快速开发

    回顾 今天VS 2019正式发布,实验一波,你安装了么?Blog.Core 预计今天会升级到 Core 3.0 版本. 哈喽大家周三好!本来今天呢要写 Id4 了,但是写到了一半,突然有人问到了关于 ...

  8. 使用MediatR重构单体应用中的事件发布/订阅

    标题:使用MediatR重构单体应用中的事件发布/订阅 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10640280.html 源代码:https ...

  9. ShortcutBadgerDemo【安卓应用角标(badge)实现方案】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 本文主要使用的开源库是 leolin310148/ShortcutBadger,但是在其基础上做了一些修改. 什么是应用角标? 1. ...

  10. CSS消除button标签的默认样式

    button{ /*消除button的默认样式*/ /*这种写法是对所有的button标签同时生效*/ margin: 0px; padding: 0px; /*自定义边框*/ border: 0px ...