小程序_小工具程序 - CSDN
小程序 订阅
小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。 展开全文
小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。
信息
中文名
小程序
主要优势
不需要下载安装即可使用
小程序发展背景
随着APP市场的饱和,大部分用户已经养成了使用习惯,开发新的APP很难在市场生存。此外,APP开发和推广成本高也是不争的事实。易观2018年3月份的报告显示,移动电商APP的下载成本高达120-200 元,而且这些后期未必能形成转化。互联网金融、二手车电商APP的新客户成本,更是动辄高达数千元。因此,不少“码农”们决定开始向小程序市场“跳槽”。 [1] 
收起全文
  • 微信小程序开发实战

    2019-04-01 14:05:00
    本套课程使用了元认知教学法,直接实战式教学,摆脱学院派的理论式讲解,对于0基础的学员可以入门编写微信小程序,过程中指导如何学习使用文档查阅接口等,通过两个完整的实战小项目的实例,入手小程序开发。
  • 小程序开发入门

    2018-11-27 16:02:26
    小程序实战入门,10天带领大家上线一款属于自己的微信小程序。微信小程序开发入门视频教程,该课程从微信小程序注册到官方开发工具、官方Demo、再到开发个人专属小程序所有知识点,包括小程序获取用户信息等功能。
  • 本课程是一个系列入门教程,目标是从 0 开始带领读者上手实战,课程以微信小程序的核心概念作为主线,介绍配置文件、页面样式文件、JavaScript 的基本知识并以指南针为例对基本知识进行扩展,另外加上开发工具的安装...

    课程介绍

    本课程是一个系列入门教程,目标是从 0 开始带领读者上手实战,课程以微信小程序的核心概念作为主线,介绍配置文件、页面样式文件、JavaScript 的基本知识并以指南针为例对基本知识进行扩展,另外加上开发工具的安装、小程序发布等内容,共 9 篇文章。

    本课程共包含四个部分。

    第一部分(第1-3篇)带你初步了解小程序是什么,然后进行小程序开发的准备工作,从注册账号到安装开发工具一应俱全。工欲善其事,必先利其器。

    第二部分(第4-6篇)。面向入门级读者介绍小程序构成的各个部分。您不需要事前准备任何知识,需要掌握的会进行说明,需要扩展的会提供信息的出处。千里之行始于足下。

    第三部分(第7-8篇)通过指南针的例子,介绍一个小程序的实现过程。通过这个实例,综合运用所学知识,使小程序开发能力进一步提高。麻雀虽小,五脏俱全。

    第四部分(第9篇)只包含一篇文章,具体介绍小程序发布的过程。使读者能够对小程序开发的全过程有一个完整的了解。编筐编篓,全在收口。

    哪怕您事先没有任何微信小程序相关技术的经验,认真学完该达人课之后,您会掌握基本的小程序开发方法,并具备自主扩展知识面,以及进行更高层次开发的能力。

    点击查看课程全部内容

    作者介绍

    薛卫国,现就职于某外企担任架构小组责任人,CSDN 博客专家,长期从事 C++ 开发,精通 UML、设计模式,创办有公众号《面向对象思考》。毕业于东北大学,曾留校在国家重点实验室工作。

    课程内容

    第01课:初识微信小程序

    要火的节奏

    最近有一则来自北京商报的新闻引起了不少人的注意,我们这里选取一部分:

    争夺流量 手机厂商“抱团”对抗微信小程序

    3月20日,小米、中兴、华为等10家手机厂商联合对外宣布,推出基于手机硬件平台的新型应用生态“快应用”及相关标准。在微信小程序用户规模日益壮大、硬件利润微薄的背景下,本次快应用的推出被看做是手机厂商与腾讯争夺流量与利益的举动。业内人士认为,对于整个市场来说,流量竞争有促进作用,但微信已经具有较强的用户黏性,十大手机厂商要想争夺用户流量并非易事。

    估计这些厂家的标准出台还需要一段时间,但是有一点可以确定的是:小程序类的开发要火。

    但如果你打开轻应用的文档可以发现两点:

    1.应用文档的信息量还很有限。2.轻应用的架构,采用的技术和微信小程序很相似。

    处于这个目的,作者赶在这个时机制作了本课程,希望可以为潮流加一份力;作为程序员,希望各位可以通过本课程的学习,在有限的时间内为自己添一份技能!

    参考资料:轻应用开发文档

    什么是小程序?

    最近一个小游戏“跳一跳”火得不得了,相信即使您自己没有玩过,身边的亲戚朋友也一定玩过。画面大致如下:

    当然了,关于玩法等等不是本文的内容,可以参照百度百科

    这就是微信小程序的成功案例了。

    微信小程序简介

    微信小程序简称小程序,张小龙在微信公开课 Pro 上发布的小程序正式上线,时间是2017年1月9日。关于小程序,张小龙在他的公开课中有过很详细的说明,大家尽可以到网上去搜,这里不再赘述,只说作者自己的理解。

    微信小程序这个词可以分解为“微信”和“小程序”两部分。

    其中“微信”可以理解为“微信中的”,指的是小程序的执行环境;当然微信在提供执行环境的同时也延长了用户使用微信的时间。

    “小程序”是说它首先是程序,然后具备轻便的特征。小程序并不像其他应用那样,它不需要安装,而是通过扫描二维码等打开后直接执行;用完以后也不需要卸载。这就是所谓用完即走的原则。

    另外,微信不会提供类似于小程序商店的地方,需要小程序提供者自己通过二维码,群分享的手段来传播,这就是所谓去中心化的形态。

    微信朋友圈提供了好友之间沟通信息的手段,订阅号提供了面向粉丝推送信息的手段,而小程序则是提供了用户通过自己的操作而与服务实现互动的手段。

    小程序相关技术介绍

    本课程的目标读者群是了解基本的 C/C++ 语法但对小程序开发完全没有经验的程序员,因此在说明微信小程序的同时,对相关技术也将进行相应的介绍。通过这种方式,可使读者能够非常顺利地学习,而无需到处寻找资料导致忘了学习微信小程序这个本来的目的。

    微信小程序推出一年多一点的时间,算是一个新事物,但是利用的技术却都是已经存在的技术。如果你稍加调查就会发现,不光是微信小程序,很多类似形态的应用都采用类似的架构:

    1. 使用 JSON 技术来表现应用的配置信息。包含应用的基本信息,页面配置和路由,应用全体的信息等。
    2. 使用经过定制 CSS+XML 技术来实现视图层的描述。画面元素,例如列表、按钮、文本框、选择框等都通过 XML 语言来描述,遵从 XML 语法,对于页面的共同风格,使用 CSS 进行定义。
    3. 使用 JavaScript 语言来实现逻辑层结构。包括用户操作的处理,系统 API 的调用等。
    4. 架构在视图层和逻辑层之间提供数据和事件传输功能,从而尽量减少难度。由于类似应有都属于轻应用,所以提供的功能都比较单一。

    具体的语法,用途等将会在使用的时候详细介绍,这里只提一下相关技术的基本情况,了解即可。

    换一种说法就是:并不需要另外自己调查,跟着本课程走下去就好。

    JSON

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于 ECMAScript(W3C 制定的 JavaScript 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

    XML

    XML(Extensible Markup Language),中文名为可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。

    在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息,比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是 Internet 环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。早在1998年,W3C 就发布了 XML1.0 规范,使用它来简化 Internet 的文档信息传输。

    CSS

    层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现 HTML 或 XML 等文件样式的计算机语言。CSS 不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。

    CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力。

    JavaScript

    JavaScript 一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    在1995年时,由 Netscape 公司的 Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为 Netscape 与 Sun 合作,Netscape 管理层希望它外观看起来像 Java,因此取名为 JavaScript。但实际上它的语法风格与 Self 及 Scheme 较为接近。

    为了取得技术优势,微软推出了 JScript,CEnvi 推出 ScriptEase,与 JavaScript 同样可在浏览器上运行。为了统一规格,再加上 JavaScript 兼容于 ECMA 标准,因此也称为 ECMAScript。

    学习方法

    微信小程序虽然是新事物,但学习方法却不是新方法。

    我们的套路是:首先生产一个最简单的小程序实例,通过这个实例介绍微信小程序的构造和想法,这算是学习这个活动中“学”的部分。然后扩展这些知识点,通过开发一个简单的小程序的过程来运用这些知识点,这算是“习”的过程。

    这是作者这些年来屡试不爽的方法。

    参考资料

    在学习和开发的过程中,我们主要会参考微信的开发文档。其原因是小程序太新了,相应的知识储备还不够丰富。虽然也可以找到一些开发方面的书籍,但是说实话,内容并不比微信本身的开发文档更详尽。

    第02课:开发环境的准备

    创建自己的小程序账号

    在开发自己的微信小程序之前,首先需要注册小程序账号,接下来我们一步一步做详细说明。

    打开浏览器,输入:mp.weixin.qq.com。

    因为是第一次使用,所以选择画面右上角的“立即注册”。

    选择左下角的“小程序”方框。

    输入邮箱、密码、确认密码、验证码,之后选择同意协议和条款。当然这里的密码不是邮箱的密码,而是正在申请的小程序账号的密码。

    最后按下“注册”按钮。

    点击“登录邮箱”按钮。打开相应的软件后,应该可以收到下面的邮件。如果没收到的话,建议看一下垃圾邮件,没准儿那里有。

    单击下半部一大片绿色的部分,就可以回到注册界面继续剩下的工作。

    选择主题类型为“个人”,然后输入管理员的姓名,身份证号码。

    输入手机号码并单击“获取验证码”,将手机接收到的验证码输入到短信验证码栏中。

    完成上述步骤,画面下部会出现一个二维码,需要用已经绑定银行卡的微信的扫一扫功能扫描该二维码进行实名认证。

    如果认证成功,画面会变成下面这个样子。

    点击“继续”按钮。

    意思就是现在后悔还来得及,如果不后悔今后就没法后悔了。我们按下“确定”按钮。

    大功告成!

    小程序管理平台

    账号申请成功之后,就可以登录“微信公众平台 | 小程序”了。在目前这个时间点虽然并不需要马上做什么。本文接下来将对其中重要的菜单功能做简单介绍。

    首页

    内容比较简单,主要是表示小程序的实时访问次数和系统公告。

    开发管理

    用户在使用小程序的时候,需要扫描二维码进入。而这个二维码需要开发者将小程序上传到腾讯服务器之后从腾讯取得。上传过程便在该页面上完成。

    过程也不复杂,一共分为三步:上传代码,提交审核和发布小程序。

    用户身份

    这个画面用来指定小程序项目的管理员和项目成员。其中项目成员又包括开发者和体验者。

    数据分析

    这个画面可以统计小程序的访问数量,对用户来源、性别、年龄分布等进行分析。

    模板消息

    这个画面可以定制微信小程序向客户发送的消息。

    客服消息

    通过这个画面可以指定小程序的客服人员,从而实现小程序的在线客服功能。

    附近的小程序

    当小程序的主体为企业、政府、媒体及其他组织时可以开通此功能。此功能有效时,小程序指定地点以后,用户可以通过微信的“附近的小程序”界面发现该小程序。

    运维中心

    一共有两个页面,分别用于查询小程序的错误日志和对客户端进行监控。

    推广

    用来自定义小程序推广关键字。

    设置

    设置分类中一共有五个页面,这里只介绍前两个。

    基本设置

    顾名思义,这里主要是用来设置小程序的基本信息。内容包括:

    1. 设定小程序名称,小程序头像;
    2. 取得小程序码;
    3. 取得认证;
    4. 设定主题信息;
    5. 其他省略。

    开发设置

    这个页面主要负责和小程序开发相关的设定信息,内容包括:

    1. 取得小程序 ID。每一个发布的小程序都需要唯一的 ID。
    2. 生成小程序秘钥。
    3. 指定服务器域名。小程序可以访问外部网站,可以上传和下载文件。但是对象服务器不是任意的,需要在这里指定。
    4. 其他省略。

    其他

    在画面的右上角,有两个链接“文档”和“社区”分别可以进入小程序开发文档和社区。在实际的学习过程中可以积极利用。

    安装开发工具

    小程序账号申请成功之后的工作就是准备开发环境。

    早期的版本在首页分类中有开发工具的下载链接,最近不知道为什么变成了访问次数统计画面。但是没有关系,可以直接点击这里,便可打开下面的下载地址页面。

    根据操作系统选择合适的下载链接。

    下载完成后打开安装程序,首先是开始画面。

    按下“下一步”按钮。

    按下“我接受”按钮。

    指定适当的安装目录后按下“安装”按钮。

    安装中……

    完成!

    接下来就可以开始微信小程序的开发之旅啦!

    第03课:微信开发者工具介绍

    第04课:小程序构成介绍——配置文件的形式和内容

    第05课:小程序构成介绍——WXML 和 WXSS

    第06课:小程序构成介绍——事件处理和数据绑定

    第07课:小程序开发实例——指南针(上)

    第08课:小程序开发实例——指南针(下)

    第09课:发布小程序

    点击查看课程全部内容

    展开全文
  • 最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了一个滴滴他们家的青桔单车小程序的前端实现,过程一言难尽,差不多两周时间过去了,发现小程序的坑远比想象的要多的多!!在实际练手中...

    这种方法,并不能反编译出所有的小程序源码,请自知!

    具体的局限请看:qwerty472123大神的md文件
    https://github.com/qwerty472123/wxappUnpacker

    下面是原文:


      最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了一个滴滴他们家的青桔单车小程序的前端实现,过程一言难尽,差不多两周时间过去了,发现小程序的坑远比想象的要多的多!!在实际练手中,完全是黑盒的,看到人家上线的小程序的效果,纯靠推测,部分效果在绞尽脑汁后能做出大致的实现,但是有些细节,费劲全力都没能做出来。很想一窥源码,查看究竟,看看大厂的前端大神们是如何规避了小程序的各种奇葩的坑。

      于是就想到获取到小程序地源文件,然后再对其进行反编译还原为源代码,来作为学习参考。我百度了各种关于小程序地反编译教程,但是感觉都不太适合像我这样地初学小白,踩了挺多坑。在这里把我重新简化好的,快速地获取一个微信小程序源码的方式记录下来。

    #一、简单聊一下xxxxx.wxapkg
    先来想想一个很简单的问题,小程序的源文件存放在哪**?**

    • 当然是在微信的服务器上。

    但是在微信服务器上,普通用户想要获取到,肯定是十分困难的,有没有别的办法呢?

    • 简单思考一下我们使用小程序的场景就会明白,当我们点开一个微信小程序的时候,其实是微信已经将它的从服务器上下载到了手机,然后再来运行的。
    • 所以我们应该可以从手机本地找到到已经下载过的小程序文件

    那么如何才能在手机里找到小程序的源文件包呢?

    • 这里只以安卓手机为例,毕竟穷逼不曾拥有过苹果手机

    • 具体目录位置直接给出:

    • 根目录/data/data/com.tencent.mm/MicroMsg/{一串16进制字符}/appbrand/pkg/

    • 在这个目录下,会发现一些 xxxxxxx.wxapkg 类型的文件,这些就是微信小程序的包

      微信小程序的格式就是:.wxapkg

      !!! PS !!!:
      这里重要声明一下:虽然微信小程序的包后缀是.wxapkg,但有一些包的依赖后缀也是.wxapkg,真正的小程序包大小1M左右,而依赖包大小2、3M甚至更多。所以一股脑的反编译.wxapkg 类型的文件可能会报错: Error: This Package is unrecognizable, please decrypted every type of file by hand.遇见这个问题的小伙伴请自知,你可能没找对包哦!

    • .wxapkg是一个二进制文件,有其自己的一套结构。

    • 微信小程序源码阅读笔记lrdcq大神的这篇博文有对.wxapkg的详细介绍,当然你也不可以不看

    • 但是这里有个,想要进入到上面这个目录的话,用手机自带的文件管理器肯定是不行的,安卓或者iPhone都要要用到第三方的文件管理器,比如:RE文件管理器,并且安卓需要取得root权限,而苹果手机肯定是要越狱的,且iphone的越狱难度>>安卓获取root,不管越狱还是root,这都太费劲,当然有能力的同学可以直接从手机上来操作,但是这里不推荐从真机上获取

    #二、准备材料
    1.node.js运行环境

    2.反编译的脚本

    3.安卓模拟器(要求自带root权限)

    #三、详细步骤
    使用安卓模拟器获取到.wxapkg文件

    不用越狱,不用root,使用电脑端的安卓模拟器来获取是一个非常简单快捷的获取方式,具体步骤如下:
    1.打开安装好的安卓模拟器,并在模拟器中安装QQ微信RE管理器

    • QQ微信在模拟器自带的应用商店里搜索下载安装即可

    • RE管理器的下载地址:https://pan.baidu.com/s/1PPBx08rNutXxhlMMJbuTpQ

      提示一下:RE管理器在模拟器的应用商店一般也能搜到!!可以直接下载

    • 下载好后直接拖拽进打开的模拟器窗口就会自动安装

    2.设置一下模拟器

    • 以我个人认为比较好用的夜神模拟器举例
    • 首先到模拟器内部设置超级用户权限

    这里写图片描述
    这里写图片描述

    • 这些操作的目的都是为了能让RE管理器顺利的获取到ROOT权限

    3.接下来在模拟器里打开微信,然后在微信中运行你想要获取的下程序(这其实是让微信把小程序的源文件包从服务器下载到了本地了)

    • 就以我说的这款共享单车的小程序举例

    • 在模拟器微信中运行一下后,直接切回模拟器桌面,运行RE浏览器 来到目录

    • 根目录/data/data/com.tencent.mm/MicroMsg/{一串16进制字符}/appbrand/pkg/

    • 就抵达了目的文件夹
      这里写图片描述

    • 你会看到发现里面的一些.wxapkg后缀的文件,就是它们没错啦,可以根据使用的时间来判断那个是你刚才从服务器下载过来的

    • 一般小程序的文件不会太大,长按,然后点右上角选项将其压缩为zip包,然后再将压缩好的包通过QQ发送到我的电脑

    • 注:如果不进行压缩的话,QQ会提示文件不可用
      这里写图片描述

    • 所以QQ的这个功能可以让我们很方便的拿到源文件,而不必到电脑目录去找模拟器的文件目录。

    • 解压。这样几步简单操作,就成功拿到了小程序的源文件了。
      #四、使用反编译脚本解包 wxapkg

    • 到这里你应该已经将反编译脚本从github下载 或者 clone 到本地某个目录

    • 打开nodejs命令窗口,如果有vscode的直接使用vscode更方便,没有安装的,打开如下这个命令行窗口:
      这里写图片描述

    • 用cd命令进入到你clone或者下载好的反编译脚本目录
      这里写图片描述

      图中的是我的命令行目录,注意:这个路径最好不要有中文,大家都知道,中文路径,经常引起一些奇奇怪怪的bug,如果路径有中文,自行解决

      把那几个反编译要用到的脚本放在上图中的目录下(这个目录根据自己的实际目录而定,图中是我的目录)
      这里写图片描述
      qwerty472123大神的脚本里面,后缀.js.json的文件才是有用的文件,其他文件是GitHub上需要的文件,当然也可以全部解压!在这里我只解压了后缀.js .json的文件)

    • node命令窗口中安装依赖:npm install

    • 安装好依赖之后,就是最后一步了,反编译 .wxapkg 文件

    • 在当前目录下输入
      node wuWxapkg.js [-d] <files…> //files就是你想要反编译的文件名
      例如:我有一个需要反编译的文件 _163200311_32.wxapkg 已经解压到了D盘根目录下,那么就输出命令
      node .\wuWxapkg.js D:\_163200311_32.wxapkg

      小技巧:注意这里斜杆别打反了,你可以输入文件名前几个字符,然后Tab键会自动补全文件名

      注意一点.wxapkg 文件名,不要有空格。有些.wxapkg 文件名中自带空格,请自行把空格去掉,或者把文件名改成其他的。路径问题自行修改!!!

    • 回车运行
      这里写图片描述

    • 反编译脚本就能一步将.wxapkg 文件还原为微信开发者工具能够运行的源文件,目录地址和你反编译的文件地址是一样的
      这里写图片描述

    • 看到这些文件结构,是不是非常熟悉!我们在微信开发者工具新增项目即可打开
      这里写图片描述

    • 运行成功,源码获取完成
      这里写图片描述

    如果运行出现了点问题:

    1、可以试试,点击开发者工具详情去掉 es6转es5的勾,勾上不校验安全域名
    2、 勾选了还是无法运行?那么请在详情里把基础版本库调低至1.5左右,再试试
    3、出现找不到某些文件的情况怎么办?我只能告诉:删!删!删! app.json
    里面,提示找不到那个文件,就将pages下注册的该页面语句暂时删除掉。删
    到可以运行为止
    4、还是无法运行?那就自己想办法吧!

    #五、两步即可完成
    至此我们就通过非常简单的方式获取到了一个想要的小程序源文件,并对其进行了反编译还原 以后想要再反编译其他的小程序,非常快速,只需要两步

    1.使用模拟器找到小程序.wxapkg文件
    2.使用nodejs反编译脚本将.wxapkg文件反编译

    使用此方法,绝大部分的小程序都能正常反编译出来,但是也会有一些特殊的情况,具体可以查看qwerty472123大神的readme.md文件

    #六、写在后面的话
    早在跳一跳小游戏火的时候,就有人通过小程序的appid和版本号,构造URL直接从服务器端下载该小程序的源码wxapkg文件。但是这种方法很快就被封了。

    上线的源代码能如此简单的被获取到,不得不说小程序的源码安全存在一些隐患,不过现在的小程序开发框架会用babel这样的打包工具把js逻辑代码揉在一个js文件里,转编译成看不懂的代码,这样,即使被获取了源码,也很难窥得蛛丝马迹。

    这里介绍的方法只想提供给像我一样的小程序新手用来学习和仿写练手,获取仿写素材。

    小程序作为微信生态内的新生力量,不仅被官方,也被很多开发者和内容创业者寄予厚望,处于对代码的安全性的考虑,这里的获取方式,不确定以后是否还行得通。


    原文传送门:行无忌的成长小屋:只需两步获取任何微信小程序源码

    END!

    展开全文
  • 备注:小程序只是突发灵感兴趣弄的,并非专业研究小程序,其实小程序API并不多,不复杂,扩展无非就是JS了。 最近用了大概两天左右的时间看了小程序的官方文档:https://mp.weixin.qq.com/cgi-bin/wx 然后有目标的...

    作者:谭东

    备注:小程序只是突发灵感兴趣弄的,并非专业研究小程序,其实小程序API并不多,不复杂,扩展无非就是JS了。

    最近用了大概两天左右的时间看了小程序的官方文档:https://mp.weixin.qq.com/cgi-bin/wx

    然后有目标的进行实践,也就是要实现个你想要的小程序,这样边实践边学习才能够有疑问,才能够更快的理解和学习小程序开发。所以后续几天就开始小程序实践和学习之旅了,期间也遇到了一些问题并且学到了很多基础知识和解决方案。接下来给大家讲解下小程序的开发基本知识和扩展知识。

    官方文档其实写的基本很详细了,我们先从工具开始说起。

    1、小程序开发者工具。

    这个工具集成了公众号网页调试和小程序调试两种开发模式。我这里使用了Beta版本,没有用正式版。因为我想体验使用其中的Git版本管理功能。下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/beta.html

    下载安装好后,先要微信扫描登录。然后选择小程序项目。

    新建小程序项目。

    选择新建小程序的项目目录,AppID没有注册的话,可以先点击下面的使用测试号即可,不影响开发。

    大致的工具界面如下图,新版有版本管理。红色圈起来的为小程序项目的一个页面包含的元素:

    工具用起来很方便、简单、直接。详细用法就不说了,主要的功能大概说下。左侧是模拟器,可以模拟安卓手机和苹果手机的效果,因为有些小程序组件在安卓和苹果上显示是有区别的,大家可以注意下。圈红的为小程序一个页面的基本组成文件元素:xx.js、xx.wxml、xx.wxss、xx.json。其实就是有JS文件、HTML文件(xx.wxml)、CSS样式文件(xx.wxss)和配置文件(xx.json)组成,非常的容易理解。我们就是在使用小程序的组件、控件来绘制UI布局,主要是xx.wxml和xx.wxss文件。xx.js负责生命周期函数和事件处理,例如:点击事件、数据请求、数据绑定等等逻辑操作。

    我们在编写完后,可以点击工具栏上的预览按钮,扫描二维码在真机上体验,也可以直接用左侧的模拟器时时预览即可。

    看完了工具,我们看下基本开发的要素和需要注意的问题吧,以免新手再次重蹈覆辙。

    看下默认的新建后的结构:

    app.json是小程序全局配置文件,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。

    大致代码结构如下:

    {
      "pages":[
        "pages/index/index",
        "pages/logs/logs"
      ],
      "window":{
        "backgroundTextStyle":"light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle":"black"
      }
    }

    pages是配置小程序所有页面,类似于注册清单。window是全局的窗口配置,如颜色、标题等等。当然每个页面也可以自己单独配置,就是页面名称.json文件。例如:page.json。不过需要注意的是,单独页面配置的json无需写window这个关键字,直接如下代码所示:

    {
      "backgroundTextStyle": "light",
      "navigationBarBackgroundColor": "#34495e",
      "navigationBarTitleText": "日记",
      "navigationBarTextStyle": "white",
      "enablePullDownRefresh": true,
      "backgroundColor": "#34495e"
    }

    那么再看工具配置文件project.config.json。

    通常大家在使用一个工具的时候,都会针对各自喜好做一些个性化配置,例如界面颜色、编译配置等等,当你换了另外一台电脑重新安装工具的时候,你还要重新配置。考虑到这点,小程序开发者工具在每个项目的根目录都会生成一个 project.config.json,你在工具上做的任何配置都会写入到这个文件,当你重新安装工具或者换电脑工作时,你只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等等一系列选项。具体详细配置大家可以看小程序官方文档有详细介绍。

    还有一个app.wxss和app.js。这个app.wxss就是全局的样式文件,也就是css文件,当然和页面配置文件一样,每个页面可以单独写页面名称.wxss。

    WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。

    新增了尺寸单位。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。

    提供了全局的样式和局部样式。和前边 app.json, page.json 的概念相同,你可以写一个 app.wxss 作为全局样式,会作用于当前小程序的所有页面,局部页面样式 page.wxss 仅对当前页面生效。

    此外 WXSS 仅支持部分 CSS 选择器

    再来看app.js,很明显是一个js文件。负责UI交互、数据绑定更新、网络请求、页面生命周期等等操作相关的都在这里。当然每个页面都有自己单独的.js文件,这个app.js可以做一些需要全局共享和操作的逻辑在里面。在这里可以调用微信小程序的很多API,也可以自己写js方法使用。

    那么我们看下一个页面的组成,基本上就是下图这些结构元素。有界面、有样式、有js交互、有配置。

    每新增一个页面都要在app.json里添加注册进去。

    一个.js文件里有生命周期的管理函数,可以在这里面做相应的操作。

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
        
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
        
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
        
      },
    
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
        
      }
    })

    我们看下最简单的一个index.wxml页面,可以当做是Html页面,只有一个text控件,里面的bindtap就是点击事件的绑定。

    <!--index.wxml-->
    <view class="container">
      <view class="usermotto">
        <text class="user-motto" bindtap='click'>{{motto}}</text>
      </view>
    </view>

    那么这个class就是index.wxss里的样式文件。里面的{{motto}}就是指向index.js里的data里定义的一个变量。小程序都是通过{{..}}两个大括号包括一个英文名字来进行变量绑定的。这样我们就可以动态更换里面的显示内容了。那么怎么更新内容呢?

    在js里使用下面的this.setData方式动态更新刷新数据:

    this.setData({ motto: "名字" })
    /**index.wxss**/
    .userinfo {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    .userinfo-avatar {
      width: 128rpx;
      height: 128rpx;
      margin: 20rpx;
      border-radius: 50%;
    }
    
    .userinfo-nickname {
      color: #aaa;
    }
    
    .usermotto {
      margin-top: 200px;
    }

    再看下index.

    js文件。

    //index.js
    //获取应用实例
    const app = getApp()
    
    Page({
      data: {
        motto: 'Hello World',
      },
      
      //事件处理函数
      click: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
        
    })

    Page函数是必须要有的,里面包含data:{  ... },用于放置数据、常量、变量等等。这里的click:function就是我们定义的点击事件。wx.navigateTo...方法就是小程序的官方API,具体其他API的用法和返回参数是什么可以看官方API文档,很详细。

    观察下,上面有个声明了app这个常量。这个就是app.js里拿到的全局管理调用app.js里的方法和常量用的。很多需要存储和全局读写、处理的都可以进行操作以及放置在app.js里。在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。通过全局函数 getApp() 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置。

    Page({
      data: { // 参与页面渲染的数据
        logs: []
      },
      onLoad: function () {
        // 页面渲染后执行
      }
    })

    小程序的组件和控件有很多,可以看做是Html的标签,对称方式使用。具体组件特性看官方文档:

    https://developers.weixin.qq.com/miniprogram/dev/component/

    为了让开发者可以很方便的调起微信提供的能力,例如获取用户信息、微信支付等等,小程序提供了很多 API 给开发者,例如:

    要获取用户的地理位置时,只需要:

    wx.getLocation({
      type: 'wgs84',
      success: (res) => {
        var latitude = res.latitude // 经度
        var longitude = res.longitude // 纬度
      }
    })

    调用微信扫一扫能力,只需要:

    wx.scanCode({
      success: (res) => {
        console.log(res)
      }
    })

    需要注意的是:多数 API 的回调都是异步,你需要处理好代码逻辑的异步问题。更多API说明和用法,看官方文档。

    https://developers.weixin.qq.com/miniprogram/dev/api/

    页面的生命周期,我之前说过了,比较重要,大家可以看下理解下。

    看下逻辑层需要注意的。除了页面的生命周期,还有页面的监听事件。onPullDownRefresh():监听用户下拉刷新事件。

    需要在app.json的window选项中或页面配置中开启enablePullDownRefresh。
    可以通过wx.startPullDownRefresh触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。
    当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。

    onReachBottom():监听用户上拉触底事件。

    可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance,默认为50px。
    在触发距离内滑动期间,本事件只会被触发一次。

    onPageScroll(Object):监听用户滑动页面事件。

    onShareAppMessage(Object):

    监听用户点击页面内转发按钮(<button> 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。

    注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮。

    onTabItemTap(Object):点击 tab 时触发。

    Page.prototype.setData(Object data, Function callback):setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。

    Object 以 key: value 的形式表示,将 this.data 中的 key 对应的值改变成 value。

    其中 key 可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].message,a.b.c.d,并且不需要在 this.data 中预先定义。

    注意:

    直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
    仅支持设置可 JSON 化的数据。
    单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
    请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。

    接下来看下小程序里的路由、跳转。

    主要有这几种方式:

    这几种方式url都可以传递参数。

    wx.navigateTo:保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。注意:目前页面路径最多只能十层。

    wx.redirectTo(OBJECT):关闭当前页面,跳转到应用内的某个页面。如果你想让页面没有返回按钮,不能返回的话,就用这个跳转方式吧。

    wx.reLaunch(OBJECT):关闭所有页面,打开到应用内的某个页面。

    wx.switchTab(OBJECT):跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。

    wx.navigateBack(OBJECT):关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。

    注意:

    1、navigateTo, redirectTo 只能打开非 tabBar 页面。
    2、switchTab 只能打开 tabBar 页面。
    3、reLaunch 可以打开任意页面。
    4、页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
    5、调用页面路由带的参数可以在目标页面的onLoad中获取。

    再看下模块化。

    可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

    需要注意的是:

    exports 是 module.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中。

    // common.js
    function sayHello(name) {
      console.log(`Hello ${name} !`)
    }
    function sayGoodbye(name) {
      console.log(`Goodbye ${name} !`)
    }
    
    module.exports.sayHello = sayHello
    exports.sayGoodbye = sayGoodbye

    ​在需要使用这些模块的文件中,使用 require(path) 将公共代码引入:

    var common = require('common.js')
    Page({
      helloMINA: function() {
        common.sayHello('MINA')
      },
      goodbyeMINA: function() {
        common.sayGoodbye('MINA')
      }
    })

    注意:require 暂时不支持绝对路径。

    接下来看下小程序的视图层,也就是wxml和wxss。

    框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。

    WXML(WeiXin Markup language) 用于描述页面的结构。

    WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

    WXSS(WeiXin Style Sheet) 用于描述页面的样式。

    组件(Component)是视图的基本组成单元。

    这里挑几个比较重要的来说。首先是列表渲染,就是我们想实现一个List列表展示的时候,要进行List数据绑定,item数据绑定、可能还会涉及到模板和数据传递等等。

    列表渲染:

    <!--wxml-->
    <view wx:for="{{array}}"> {{item}} </view>
    // page.js
    Page({
      data: {
        array: [1, 2, 3, 4, 5]
      }
    })

    在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item。

    <view wx:for="{{array}}">
      {{index}}: {{item.message}}
    </view>

    使用 wx:for-item 可以指定数组当前元素的变量名,

    使用 wx:for-index 可以指定数组当前下标的变量名:

    <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
      {{idx}}: {{itemName.message}}
    </view>

    wx:for 也可以嵌套。类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:

    <block wx:for="{{[1, 2, 3]}}">
      <view> {{index}}: </view>
      <view> {{item}} </view>
    </block>

    如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <input/> 中的输入内容,<switch/> 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。

    wx:key 的值以两种形式提供:

    字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
    保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:
    当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

    如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

    条件渲染:

    <!--wxml-->
    <view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
    <view wx:elif="{{view == 'APP'}}"> APP </view>
    <view wx:else="{{view == 'MINA'}}"> MINA </view>
    // page.js
    Page({
      data: {
        view: 'MINA'
      }
    })

    在框架中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块。

    因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。

    相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。

    一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。

    还可能会涉及到模板template,可以在模板中定义代码片段,然后在不同的地方调用。

    使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:

    <!--
      index: int
      msg: string
      time: string
    -->
    <template name="msgItem">
      <view>
        <text> {{index}}: {{msg}} </text>
        <text> Time: {{time}} </text>
      </view>
    </template>

    使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:

    <template is="msgItem" data="{{...item}}"/>
    Page({
      data: {
        item: {
          index: 0,
          msg: 'this is a template',
          time: '2016-09-15'
        }
      }
    })

    is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:

    <template name="odd">
      <view> odd </view>
    </template>
    <template name="even">
      <view> even </view>
    </template>
    
    <block wx:for="{{[1, 2, 3, 4, 5]}}">
    	<template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
    </block>

    模板拥有自己的作用域,只能使用 data 传入的数据以及模版定义文件中定义的 <wxs /> 模块。

    另外,target(触发事件的源组件)和currentTarget(事件绑定的当前组件)也比较重要,大家可以自行看例子和文档学习。

    dataset:在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE。 书写方式: 以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写)如data-element-type,最终在 event.currentTarget.dataset 中会将连字符转成驼峰elementType。

    <view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
    Page({
      bindViewTap:function(event){
        event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
        event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
      }
    })

    小程序的引用,如引用外部css文件、引入js文件、引入wxml模板文件等等。

    WXML 提供两种文件引用方式import和include。

    import可以在该文件中使用目标文件定义的template,如:在 item.wxml 中定义了一个叫item的template:

    <!-- item.wxml -->
    <template name="item">
      <text>{{text}}</text>
    </template>

    在 index.wxml 中引用了 item.wxml,就可以使用item模板:

    <import src="item.wxml"/>
    <template is="item" data="{{text: 'forbar'}}"/>

    import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。

    include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置,如:

    <!-- index.wxml -->
    <include src="header.wxml"/>
    <view> body </view>
    <include src="footer.wxml"/>
    <!-- header.wxml -->
    <view> header </view>
    <!-- footer.wxml -->
    <view> footer </view>

    再讲一个wxs文件,不太常用。WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

    注意:
    1、wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
    2、wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致。
    3、wxs 的运行环境和其他 javascript 代码是隔离的,wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API。
    4、wxs 函数不能作为组件的事件回调。
    5、由于运行环境的差异,在 iOS 设备上小程序内的 wxs 会比 javascript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。
    以下是一些使用 WXS 的简单示例。

    页面渲染:

    <!--wxml-->
    <wxs module="m1">
    var msg = "hello world";
    
    module.exports.message = msg;
    </wxs>
    
    <view> {{m1.message}} </view>

    页面输出:

    hello world

    数据处理:

    // page.js
    Page({
      data: {
        array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
      }
    })
    <!--wxml-->
    <!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
    <wxs module="m1">
    var getMax = function(array) {
      var max = undefined;
      for (var i = 0; i < array.length; ++i) {
        max = max === undefined ? 
          array[i] : 
          (max >= array[i] ? max : array[i]);
      }
      return max;
    }
    
    module.exports.getMax = getMax;
    </wxs>
    
    <!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
    <view> {{m1.getMax(array)}} </view>

    页面会输出5。

    WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内,或以 .wxs 为后缀名的文件内。

    每一个 .wxs 文件和 <wxs> 标签都是一个单独的模块。每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。

    可以直接创建 .wxs 文件,在其中直接编写 WXS 脚本。

    var foo = "'hello world' from comm.wxs";
    var bar = function(d) {
      return d;
    }
    module.exports = {
      foo: foo,
      bar: bar
    };

    在.wxs文件里面编写了 WXS 代码。该 .wxs 文件可以被其他的 .wxs 文件 或 WXML 中的 <wxs> 标签引用。

    每个 wxs 模块均有一个内置的 module 对象。exports:通过该属性,可以对外共享本模块的私有变量与函数。

    // /pages/tools.wxs
    
    var foo = "'hello world' from tools.wxs";
    var bar = function (d) {
      return d;
    }
    module.exports = {
      FOO: foo,
      bar: bar,
    };
    module.exports.msg = "some msg";
    <!-- page/index/index.wxml -->
    
    <wxs src="./../tools.wxs" module="tools" />
    <view> {{tools.msg}} </view>
    <view> {{tools.bar(tools.FOO)}} </view>

    页面输出:

    some msg
    'hello world' from tools.wxs

    在.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数。

    引用的时候,要注意如下几点:

    1、只能引用 .wxs 文件模块,且必须使用相对路径。
    2、wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
    3、如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

    module 属性是当前 <wxs> 标签的模块名。在单个 wxml 文件内,建议其值唯一。有重复模块名则按照先后顺序覆盖(后者覆盖前者)。不同文件之间的 wxs 模块名不会相互覆盖。module 属性值的命名必须符合下面两个规则:

    1、首字符必须是:字母(a-zA-Z),下划线(_)。
    2、剩余字符可以是:字母(a-zA-Z),下划线(_), 数字(0-9)。

    src 属性可以用来引用其他的 wxs 文件模块。引用的时候,要注意如下几点:

    1、只能引用 .wxs 文件模块,且必须使用相对路径。
    2、wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
    3、如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

    注意:
    1、<wxs> 模块只能在定义模块的 WXML 文件中被访问到。使用 <include> 或 <import> 时,<wxs> 模块不会被引入到对应的 WXML 文件中。
    2、<template> 标签中,只能使用定义该 <template> 的 WXML 文件中定义的 <wxs> 模块。

    再看下官方给出的小程序性能优化建议。

    setData 是小程序开发中使用最频繁的接口,也是最容易引发性能问题的接口。在介绍常见的错误用法前,先简单介绍一下 setData 背后的工作原理。

    小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。而 evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。

    常见的 setData 操作错误:
    1. 频繁的去 setData。

    在我们分析过的一些案例里,部分小程序会非常频繁(毫秒级)的去setData,其导致了两个后果:Android 下用户在滑动时会感觉到卡顿,操作反馈延迟严重,因为 JS 线程一直在编译执行渲染,未能及时将用户操作事件传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层;
    渲染有出现延时,由于 WebView 的 JS 线程一直处于忙碌状态,逻辑层到页面层的通信耗时上升,视图层收到的数据消息时距离发出时间已经过去了几百毫秒,渲染的结果并不实时;
    2. 每次 setData 都传递大量新数据。

    由setData的底层实现可知,我们的数据传输实际是一次 evaluateJavascript 脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程,

    3. 后台态页面进行 setData。

    当页面进入后台态(用户不可见),不应该继续去进行setData,后台态页面的渲染用户是无法感受的,另外后台态页面去setData也会抢占前台页面的执行。

    图片资源:
    目前图片资源的主要性能问题在于大图片和长列表图片上,这两种情况都有可能导致 iOS 客户端内存占用上升,从而触发系统回收小程序页面。

    图片对内存的影响:
    在 iOS 上,小程序的页面是由多个 WKWebView 组成的,在系统内存紧张时,会回收掉一部分 WKWebView。从过去我们分析的案例来看,大图片和长列表图片的使用会引起 WKWebView 的回收。

    图片对页面切换的影响:
    除了内存问题外,大图片也会造成页面切换的卡顿。我们分析过的案例中,有一部分小程序会在页面中引用大图片,在页面后退切换中会出现掉帧卡顿的情况。当前我们建议开发者尽量减少使用大图片资源。

    代码包大小的优化:
    小程序一开始时代码包限制为 1MB,但我们收到了很多反馈说代码包大小不够用,经过评估后我们放开了这个限制,增加到 2MB 。代码包上限的增加对于开发者来说,能够实现更丰富的功能,但对于用户来说,也增加了下载流量和本地空间的占用。开发者在实现业务逻辑同时也有必要尽量减少代码包的大小,因为代码包大小直接影响到下载速度,从而影响用户的首次打开体验。除了代码自身的重构优化外,还可以从这两方面着手优化代码大小:

    控制代码包内图片资源:
    小程序代码包经过编译后,会放在微信的 CDN 上供用户下载,CDN 开启了 GZIP 压缩,所以用户下载的是压缩后的 GZIP 包,其大小比代码包原体积会更小。 但我们分析数据发现,不同小程序之间的代码包压缩比差异也挺大的,部分可以达到 30%,而部分只有 80%,而造成这部分差异的一个原因,就是图片资源的使用。GZIP 对基于文本资源的压缩效果最好,在压缩较大文件时往往可高达 70%-80% 的压缩率,而如果对已经压缩的资源(例如大多数的图片格式)则效果甚微。

    及时清理没有使用到的代码和资源:
    在日常开发的时候,我们可能引入了一些新的库文件,而过了一段时间后,由于各种原因又不再使用这个库了,我们常常会只是去掉了代码里的引用,而忘记删掉这类库文件了。目前小程序打包是会将工程下所有文件都打入代码包内,也就是说,这些没有被实际使用到的库文件和资源也会被打入到代码包里,从而影响到整体代码包的大小。

    下面将会讲解一些开发中遇到的问题:

    列表绑定渲染数据、跳转传值、小程序的工具调试使用、小程序授权弹窗、小程序客服反馈、小程序支付、小程序获取unionId和openId、小程序第三方框架、UI库等。

     

     

    这个是开源share的,github地址:https://github.com/jaychou2012/wx_note

     

     

    持续更新中,敬请关注... ...

    展开全文
  • 分类界面,左边是一级目录,右边是一级目录对应的二级目录,根据这个需求,我们数据设计的结构一定是数组嵌套数组,第一个数组包含一级目录数据,嵌套的数组包含的是二级目录的数据。 wxml代码: ...

    分类界面,左边是一级目录,右边是一级目录对应的二级目录,根据这个需求,我们数据设计的结构一定是数组嵌套数组,第一个数组包含一级目录数据,嵌套的数组包含的是二级目录的数据。

    wxml代码:

    <view class="page">
    
      <!--左侧栏-->
      <view class="nav_left">
        <block wx:for="{{cateItems}}" wx:key="unique">
          <!--当前项的id等于item项的id,那个就是当前状态-->
          <!--用data-index记录这个数据在数组的下标位置,使用data-id设置每个item的id值,供打开2级页面使用-->
          <view class="nav_left_items {{curNav == item.cate_id ? 'active' : ''}}" bindtap="switchRightTab" data-index="{{index}}" data-id="{{item.cate_id}}">{{item.cate_name}}</view>
        </block>
      </view>
      <!--右侧栏-->
      <view class="nav_right">
      <!--如果有数据,才遍历项-->
        <view wx:if="{{cateItems[curIndex].ishaveChild}}">
          <block wx:for="{{cateItems[curIndex].children}}" wx:key="unique">
            <view class="nav_right_items" data-id="{{item.DetailId}}" bindtap="isDetail"> 
              <image src="{{item.image}}"></image>
              <text>{{item.name}}</text>
            </view>
          </block>
        </view>
        <!--如果无数据,则显示数据-->
        <view class="nodata_text" wx:else>该分类暂无数据</view>
      </view>
    
    </view>

    nav_left_items {{curNav == item.cate_id ? 'active' : ''}} 在classify.js代码中已经说了curNav的作用,就是在这里实现的。

    根据是否和一级目录cate_id相同,来判断是否点亮文字。相同执行.nav_left_items.active样式,不相同则执行.nav_left_items样式

    wxss:

    /*左侧栏主盒子*/  
    .nav_left{  
    /*设置行内块级元素(没使用定位)*/  
    display: inline-block; width: 25%; height: 100%; background: #f5f5f5; text-align: center;  }  
    /*左侧栏list的item*/  
    .nav_left .nav_left_items{ height: 80rpx;line-height: 80rpx;font-size: 28rpx;  border-bottom: 1px solid #dedede; }  
    /*左侧栏list的item被选中时*/  
    .nav_left .nav_left_items.active{background: #fff; color: #f0145a; }  
    /*右侧栏主盒子*/  
    .nav_right{ 
    /*右侧盒子使用了绝对定位*/  
    position: absolute; top: 0;right: 0; flex: 1; width: 75%; height: 1000rpx;padding: 10rpx; box-sizing: border-box; background: #fff; }  
    /*右侧栏list的item*/  
    .nav_right .nav_right_items{ float: left;width: 33.33%;height: 220rpx;text-align: center; }  
    .nav_right .nav_right_items image{  width:120rpx; height:120rpx;margin-top: 25rpx;}  
    .nav_right .nav_right_items text{display: block; margin-top: 25rpx;  ont-size: 28rpx; color: black;
    /*设置文字溢出部分为...*/overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } 
    .nodata_text{color: black;font-size: 28rpx;  text-align: center; }

    js:

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        cateItems: [
          {
            cate_id: 1,
            cate_name: "护肤",
            ishaveChild: true,
            children:
              [
                {
                  child_id: 1,
                  name: '洁面皂',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161208/148117972563.jpg"
                },
                {
                  child_id: 2,
                  name: '卸妆',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161207/148110444480.jpg"
                },
                {
                  child_id: 3,
                  name: '洁面乳',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161208/148117973270.jpg"
                },
                {
                  child_id: 4,
                  name: '面部祛角质',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161208/148117981591.jpg"
                }
              ]
          },
          {
            cate_id: 2,
            cate_name: "彩妆",
            ishaveChild: true,
            children:
              [
                {
                  child_id: 1,
                  name: '气垫bb',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/14815381301.jpg"
                },
                {
                  child_id: 2,
                  name: '修容/高光',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/14815381411.jpg"
                },
                {
                  child_id: 3,
                  name: '遮瑕',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/148153815181.jpg"
                },
                {
                  child_id: 4,
                  name: '腮红',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/148153815759.jpg"
                },
                {
                  child_id: 5,
                  name: '粉饼',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/148153816983.jpg"
                },
                {
                  child_id: 6,
                  name: '粉底',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/148153817721.jpg"
                },
                {
                  child_id: 7,
                  name: '蜜粉/散粉',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161212/148153819354.jpg"
                },
                {
                  child_id: 8,
                  name: '隔离霜',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161215/148179053369.jpg"
                }
              ]
          },
          {
            cate_id: 3,
            cate_name: "香水/香氛",
            ishaveChild: true,
            children:
              [
                {
                  child_id: 1,
                  name: '淡香水EDT',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161213/14815978910.jpg"
                },
                {
                  child_id: 2,
                  name: '浓香水EDP',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161213/148159789883.jpg"
                },
                {
                  child_id: 3,
                  name: '香体走珠',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161213/14815979307.jpg"
                },
                {
                  child_id: 4,
                  name: '古龙香水男士的最爱',
                  image: "http://mz.djmall.xmisp.cn/files/logo/20161213/148159765589.jpg"
                }
              ]
          },
          {
            cate_id: 4,
            cate_name: "个人护理",
            ishaveChild: false,
            children: []
          }
        ],
        curNav: 1,
        curIndex: 0
      },
    
      //事件处理函数  
      switchRightTab: function (e) {
        // 获取item项的id,和数组的下标值  
        let id = e.target.dataset.id,
          index = parseInt(e.target.dataset.index);
        // 把点击到的某一项,设为当前index  
        this.setData({
          curNav: id,
          curIndex: index
        })
      },
    
      isDetail:function(e){
        console.log(e.currentTarget.dataset.id);
        wx.navigateTo({
          url: "../Detail/Detail?child_id=" + e.currentTarget.dataset.id
        })
      },
    
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        
      },
    
    
    })

    cateItems 展示的数据
    curNav 控制当前那个按钮点亮
    curIndex 根据此参数来拿第几个分类的数据
    switchRightTab 分类tab事件的处理

    cateItems里的数据每一个对象都是一个品类的数据,拿第一个品类护肤来说,

    cate_id 识别的id
    cate_name 一级分类名称
    ishaveChild 判断是否有子集
    children 二级目录的数据

    转载于:https://www.cnblogs.com/joe235/p/11454114.html

    展开全文
  • 很久前学写的一个做医院排行和分类归纳的小程序,今天就把其中的一部分内容分享出来。 先上效果图给大家看看: 可以进行前三排名,还可进行综合医院和三甲医院排名。 当然你要是活学活用的话可以...
  • data:{ currentSwiper: 0, recom_list: [{ avatar: 'https://sucai.suoluomei.cn/sucai_zs/images/20191121093322-1.png', name: '小禾', college: '圣迪斯哥美容博士', praise: '666'...
  • 小程序分类页实现

    2019-06-19 11:12:17
    分类界页面中,左边是一级目录,右边是一级目录对应的二级目录,根据这个需求,我们数据设计的结构是数组嵌套数组,第一个数组包含一级目录数据,嵌套的数组包含的是二级目录的数据。所以不多说,直接上代码吧。...
  • 获取到json中的数据,通过“\n”转义,此时我们需要通过正则表达式来替换一下 replace(/↵/g, ‘\n’); 在页面中可以这样 我长得好看 \n 我长得也好看 出来的结果就是 我长得好看 我长得也好看 ...
  • 通常我们想要在原有的数组上追加...小程序js页面的data: data:{ list:[] } 在方法里面,当我们要追加的时候: method:function(){ var element = 'hello world!' this.setData({ list:this.data.list...
  • wxml: &lt;!--按钮--&gt; &lt;view class="more" bindtap="showedit"&gt;{{editText}}&lt;/view&gt; &lt;!--内容--&gt; &lt;view class="... &
  • 下面我们介绍一下如何开发一个Hello World的小程序。 微信开发者工具下载 访问(https://mp.weixin.qq.com),用小程序账号登录后,按照如下步骤下载微信开发者工具。 1、点击【文档】链接 2、点击【开发】...
  • 企业 政府 媒体 ... :)填写企业信息不能使用和之前的公众号账户相同的...账户自动验证后,自动认证通过,并将认证资金退回公司对公账户,费用在1元内随机小程序发布流程开发实践这次的demo项目为农历和公历的转换器,重在体验
  • 都是些小程序源码,有的还有后台,适合小白、也适合学过了的、也适合做外包的,要的可以取...https://www.douban.com/group/topic/113284790/o2o微信小程序源码-专门针对o2o类别的小程序源码集合【更新整理中...】ht...
  • 个人类型和海外类型的小程序不支持 web-view 标签 也就是说个人申请的小程序,就别想跳转了!!!! 1.开发的时候,我们难免碰到要跳转到其他网页中去那该怎么实现呢? 2.例如我想点击一个按钮,跳转到百度(百度...
  • 微信小程序入门教程+案例demo 尊重原创,转载请注明出处:原文查看惊喜更多 http://blog.csdn.net/qq137722697 首先摆在好姿态,——微信小程序开发也就那么回事。你只需要一点点css(真的只要一点点)的基础就...
  • 微信小程序+java后台

    2018-03-21 21:30:58
    博主是大四学生,毕业设计做的是微信小程序+java后台。陆陆续续经历了三个月(因为白天要实习又碰上过年玩了一阵子),从对微信小程序一无所知到完成毕设,碰到许多问题,在跟大家分享一下自己的经历和一个小程序...
  • 哈喽,大家上午好,萍子又来啦,本人最近一段时间一直在做小程序的项目,大大小小的坑真的是踩了不小,无奈本人啊还老是忘记自己究竟踩过那些坑,但是不得不说虽然小程序尚还有很多不完善的地方,但是还是蛮强大的啦...
  • 微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 正文: 一:微信小程序跳转 使用限制 需要用户触发跳转 从 2.3.0 版本开始,若用户未点击小程序页面任意位置,则开发者将无法调用此接口...
1 2 3 4 5 ... 20
收藏数 3,849,383
精华内容 1,539,753
关键字:

小程序