[TOC]
- 2017 年度百度百科十大热词之一
- 微信小程序,简称小程序,英文名 Mini Program,是一种不需要下载安装即可使用的应用 (
张小龙对其的定义是无需安装,用完即走,实际上是需要安装的,只不过小程序的体积特别小,下载速度很快,用户感觉不到下载的过程
)- 小程序刚发布的时候要求压缩包的体积不能大于 1M,,否则无法通过,在2017年4月做了改进,由原来的1M提升到2M;
- 2017年1月9日0点,万众瞩目的微信第一批小程序正式低调上线。
- 微信有海量⽤⼾,⽽且粘性很⾼,在微信⾥开发产品更容易触达⽤⼾;
- 推⼴app 或公众号的成本太⾼。
- 开发适配成本低。
- 容易⼩规模试错,然后快速迭代。
- 跨平台。
- 安装微信小程序开发工具,建议安装稳定版进行开发
- 注册小程序账号
- 使用注册的appid进行使用,如果是测试号会限制很多功能
在官网登录成功后可以看到下面的界面,然后复制你的APPID,悄悄的保存起来,
不要给别⼈看到
。
- 打开开发者工具,第一次打开需要扫码登陆
- 新建小程序项目
- 填写项目信息
- 新建成功
详细的使⽤,可以查看官⽹:
- 点击
工具栏
–>详情
–>本地设置
,除了默认勾选,需要勾选其他的几个如:增强编译、不校验合法域名…
问题描述:很久没有进行开发了,小程序的名称跟原始id都忘记了,找回需要先填写,如何解决
解决:首先
[查询自己的原始id](https://developers.weixin.qq.com/community/develop/doc/000ea0f82d4f58b41589642b456809)
,在这个网站能查询到自己的原始id,再通过这个原始id进行找回
小程序框架的⽬标是通过尽可能简单、⾼效的⽅式让开发者可以在微信中开发具有原⽣APP体验的服务。
⼩程序框架提供了⾃⼰的视图层描述语⾔
WXML 和 WXSS
,以及 JavaScript ,并在视图层与逻辑层间提供了数据传输和事件系统
,让开发者能够专注于数据与逻辑。
- 通过以上对⽐得出传统web是
三层结构
。⽽微信⼩程序是四层结构
,多了⼀层配置.json
- 当这几个文件在同一级目录下且命名相同(后缀不同),可以互相引用却不用导入
传统web | 微信小程序 | |
---|---|---|
项目骨架、结构 | HTML | WXML |
页面样式 | CSS | WXSS |
项目逻辑 | Javascript | Javascript |
配置 | 无 | JSON |
- 项目目录图解:
- 以
app
开头的文件是应用程序级别的文件,更改一处全局生效。而页面pages
的配置优先级高于全局配置(就近原则
)- 小程序是允许你修改文件目录名的
⼀个⼩程序应⽤程序会包括最基本的两种配置⽂件。⼀种是全局的app.json 和 ⻚⾯⾃⼰的page.json
app.json
是当前⼩程序的全局配置,包括了⼩程序的所有⻚⾯路径、界⾯表现、⽹络超时时间、底部tab等。普通快速启动项⽬⾥边的 app.json 配置- 代码
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
- 字段的含义
1)pages 字段⸺⽤于描述当前⼩程序所有⻚⾯路径,这是为了让微信客⼾端知道当前你的⼩程序⻚⾯定义在哪个⽬录。
默认显示此字段中的第一项
2)window 字段⸺定义⼩程序所有⻚⾯的顶部背景颜⾊,⽂字颜⾊定义等。
3)完整的配置信息请参考 app.json配置
更多配置详细请看
[app配置文档](https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html)
- 这⾥的
page.json
其实⽤来表⽰⻚⾯⽬录下的 page.json 这类和⼩程序⻚⾯相关的配置。 开发者可以独⽴定义每个⻚⾯的⼀些属性,如顶部颜⾊、是否允许下拉刷新等等。 ⻚⾯的配置只能设置 app.json 中部分 window 配置项的内容,⻚⾯中配置项会覆盖 app.json 的 window 中相同的配置项。- 常用配置属性列举:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜⾊,如 #000000 |
navigationBarTextStyle | String | white | 导航栏标题颜⾊,仅⽀持 black / white |
navigationBarTitleText | String | 导航栏标题⽂字内容 | |
backgroundColor | HexColor | #ffffff | 窗⼝的背景⾊ |
backgroundTextStyle | String | dark | 下拉loading 的样式,仅⽀持 dark / light |
enablePullDownRefresh | Boolean | false | 是否全局开启下拉刷新。 详⻅ Page.onPullDownRefresh |
onReachBottomDistance | Number | 50 | ⻚⾯上拉触底事件触发时距⻚⾯底部距离,单位为px。 详⻅ Page.onReachBottom |
disableScroll | Boolean | false | 设置为 true 则⻚⾯整体不能上下滚动;只在⻚⾯配置中有效,⽆法在 app.json 中设置该项 |
⼩程序根⽬录下的
sitemap.json
⽂件⽤于配置⼩程序及其⻚⾯是否允许被微信索引。主要服务于搜索
- 注册小程序。接受一个
Object
参数,其指定小程序的生命周期回调等。- App() 必须在
**app.js**
中调用,必须调用且只能调用一次。不然会出现无法预期的后果- 相应的app()参数在下方的
小程序生命周期中有指出
**getApp(Object object)**
- 获取到小程序全局唯一的
App
实例。- 代码示例
// other.js
var appInstance = getApp()
console.log(appInstance.globalData) // I am global dat
//或者
const {GbaseUrl} =getApp() //GbaseUrl是自己在app.js定义的全局变量
- Object object
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
allowDefault | boolean | false | 否 | 在 App 未定义时返回默认实现。当App被调用时,默认实现中定义的属性会被覆盖合并到App中。一般用于独立分包 | 2.2.4 |
- 注意
- 不要在定义于
App()
内的函数中,或调用App
前调用getApp()
。使用this
就可以拿到 app 实例。- 通过
getApp()
获取实例之后,不要私自调用生命周期函数
整个小程序学习过程中遇到的 所需基础知识 或 补充知识 将整合至此
相关知识点本人在
一二阶段补缺笔记
中有记录,在此便只举例大概,不详细记录
- Flex基本概念
- Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
- 任何一个容器都可以指定为 Flex 布局。
- display: ‘flex’
- 这部分是一阶段基础知识,可看文档学习
- 在小程序中,通常使用
代替
作为容器来做布局–>代码示例在
第一章的第三小节第三点
详见下方
杂记-初学阶段遇到的问题与解决-问题Ⅷ
自行补充学习,相关知识点本人在
一二阶段补缺笔记
中有记录,便不再赘述
- 屏幕的分辨率
- 设备能控制显示的最小单元,可以把物理像素看成是对应的像素点
设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用并控制的
虚拟像素
(比如:CSS 像素,只是在 android 机中 CSS 像素就不叫”CSS 像素”了而是叫”设备独立像素”),然后由相关系统转换为物理像素。
- 概念
- dpr: 设备像素比,物理像素/设备独立像素 = dpr, 一般以 Iphon6 的 dpr 为准 dpr = 2
- PPI: 一英寸显示屏上的像素点个数
- DPI:最早指的是打印机在单位面积上打印的墨点数,墨点越多越清晰
- 不同机型对比表
- 部分机型图示
相关知识点本人在
一二阶段补缺笔记
中有记录,想详细查阅可以去看,这是个面试考点
- 为什么做
viewport
适配 ?
a) 手机厂商在生产手机的时候大部分手机默认页面宽度为 980px
b) 手机实际视口宽度都要小于 980px,如: iphone6 为 750px
c) 开发需求需要将 980 的页面完全显示在手机屏幕上且没有滚动条- 代码实现
<meta name="viewport" content="width=device-width,initial-scale=1.0">
- 为什么做
rem
适配?
a) 机型太多,不同的机型屏幕大小不一样
b) 需求:一套设计稿的内容在不同的机型上呈现的效果一致,根据屏幕大小不同的变化,页面中的内容也相应变化
- 原生代码实现:
function remRefresh() {
let clientWidth = document.documentElement.clientWidth;
// 将屏幕等分 10 份
let rem = clientWidth / 10;
document.documentElement.style.fontSize = rem + 'px';
document.body.style.fontSize = '12px';
}
window.addEventListener('pageshow', () => {
remRefresh()
})
// 函数防抖
let timeoutId;
window.addEventListener('resize', () => {
timeoutId && clearTimeout(timeoutId);
timeoutId = setTimeout(() =>{
remRefresh()
}, 300)
})
- 第三方库实现
lib-flexible + px2rem-loader
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合
WXML
,可以构建出页面的结构。WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
该部分将
截取官方文档
并加以注解
- WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
- WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
- 与 CSS 相比,WXSS 扩展的特性有:
- 响应式⻓度单位:即尺寸单位 -->
rpx
- 样式导入
- 注意:
当页面文件在同一级目录下且命名相同(后缀不同),可以互相引用却不用导入
rpx(responsive pixel)
: 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在iPhone6
上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
- 建议与注意点:
- 开发微信小程序时
推荐设计师可以用iPhone6作为视觉稿的标准
–>即只有在iPhone6
标准中才可以一比二换算
,更方便- 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况
- 使用
@import
语句可以导入外联样式表,也可以和less中的导⼊混⽤,@import
后跟需要导入的外联样式表的相对路径
(只⽀持相对路径),用;
表示语句结束。
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
框架组件上支持使用 style、class 属性来控制组件的样式。
style
:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度
<view style="color:{{color}};" />
class
:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.
,样式类名之间用空格分隔
<view class="normal_view" />
WXML(WeiXin Markup Language)是框架设计的⼀套标签语⾔,结合基础组件、事件系统,可以构建出⻚⾯的结构。
该部分将
截取官方文档
加以自己见解说明,同学们也可以直接去看文档
- WXML 中的动态数据均来自对应 Page 的 data。
- Mustache 语法{{}}视作运算标记,里面的内容表示表达式
- 此处是单向绑定(数据驱动视图),双向绑定出现的场景如(input等)将在下方
四-3、双向绑定
处记录简单绑定
:数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于:
//pages.wxml
{{ message }}
// pages.js
Page({
data: {
message: 'Hello MINA!'
}
})
- 绑定
boolean
类型(需要在双引号之内)
true
:boolean 类型的 true,代表真值。false
: boolean 类型的 false,代表假值。
_特别注意:不要直接写 _
**_checked="false"_**
,其计算结果是一个字符串,转成 boolean 类型后代表真值
可以在
{{}}
内进行简单的运算,支持的有如下几种方式:
- 三元运算
Hidden
- 算数运算
{{a + b}} + {{c}} + d
//view中的内容为 `3 + 3 + d`。
//pages.js
Page({
data: { a: 1, b: 2, c: 3
}
})
- 逻辑判断
- 字符串运算
{{"hello" + name}}
Page({
data:{name: 'MINA}
})
- 数据路径运算
{{object.key}} {{array[0]}}
//view中的内容为 hello MINA
Page({
data: {
object: {
key: 'Hello '
},
array: ['MINA']
}
})
也可以在 Mustache 内直接进行组合,构成新的对象或者数组。
- 数组 --> 最终组合成数组
[0, 1, 2, 3, 4]
。
{{item}}
Page({
data: { zero: 0 }
})
- 对象 -->
- 最终组合成的对象是
{for: 1, bar: 2}
Page({
data: {a: 1, b: 2}
})
- 也可以用扩展运算符
...
来将一个对象展开–>最终组合成的对象是{a: 1, b: 2, c: 3, d: 4, e: 5}
。
Page({
data: {
obj1: { a: 1, b: 2 },
obj2: { c: 3, d: 4}
}
})
- 如果对象的 key 和 value 相同,也可以间接地表达。–>最终组合成的对象是
{foo: 'my-foo', bar:'my-bar'}
Page({
data: {
foo: 'my-foo',
bar: 'my-bar'
}
})
注意
:上述方式可以随意组合,但是如有存在变量名相同的情况,后边的会覆盖前面 --> 最终组合成的对象是{a: 5, b: 3, c: 6}
。
Page({
data: {
obj1: { a: 1, b: 2},
obj2: { b: 3, c: 4},
a: 5
}
})
注意
: 花括号和引号之间如果有空格,将最终被解析成为字符串
{{item}}
等同于
{{item}}
data-*
的命名与使用
- 同一容器中可以存在多个
data-*
- 凡是以
data-
开头的数据,都会在event的currentTarget
中体现,且回缺省data-
(data-id --> id)data-*
后面接的单词将自动转换 第一个单词首字母小写,第二个及之后的单词首字母大写 (data-post-my-id --> postMyId)
- 在组件上使用
wx:for
控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。- 默认数组的当前项的下标变量名默认为
index
,数组当前项的变量名默认为item
- 使用
wx:for-item
可以指定数组当前元素的变量名,使用wx:for-index
可以指定数组当前下标的变量名:
{{idx}}: {{itemName.message}}
wx:for
也可以嵌套,下边是一个九九乘法表
{{i}} * {{j}} = {{i * j}}
类似
block wx:if
,也可以将wx:for
用在标签上,以渲染一个包含多节点的结构块。例如:
{{index}}:
{{item}}
注意:
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用
wx:key
来指定列表中项目的唯一的标识符。
wx:key
的值以两种形式提供
- 字符串,代表在for循环的array中
item的某个property
,该property的值需要是列表中唯一的字符串或数字,且不能动态改变。- 保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字
。
//id是posts数组中的对象里的一个属性
wx:key
的意义当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件
,框架会确保他们被重新排序,而不是重新创建
,以确保使组件保持自身的状态,并且提高列表渲染时的效率。如不提供
wx:key
,会报一个warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
wx:for
的值为字符串时,会将字符串解析成字符串数组
{{item}}
等同于
{{item}}
{{item}}
等同于
{{item}}
- 在框架中,使用
wx:if=""
来判断是否需要渲染该代码块:
True
- 也可以用
wx:elif
和wx:else
来添加一个 else 块:
1
2
3
因为
wx:if
是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个标签将多个组件包装起来,并在上边使用
wx:if
控制属性
view1
view2
注意:
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性
wx:if
vs hidden
- 因为
wx:if
之中的模板也可能包含数据绑定,所以当wx:if
的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。- 同时
wx:if
也是惰性的,如果在初始渲染条件为false
,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,
hidden
就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
- 一般来说,
wx:if
有更高的切换消耗而hidden
有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用hidden
更好,如果在运行时条件不大可能改变则wx:if
较好。
- WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用
- 模板拥有自己的
作用域
,只能使用data
传入的数据以及模板定义文件中定义的模块。
使用 name 属性,作为模板的名字。然后在
内定义代码片段,如
{{index}}: {{msg}}
Time: {{time}}
- 使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:
Page({
data: {
item: { index: 0, msg: 'this is a template', time: '2016-09-15'}
}
})
- is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:
odd
even
WXML 提供两种文件引用方式
import
和include
- 在 item.wxml 中定义了一个叫
item
的template
:
{{text}}
- 在 index.wxml 中引用了 item.wxml,就可以使用
item
模板:
import有作用域的概念,即只会 import 目标文件中定义的 template,而不会import目标文件import的template。
如:C import B,B import A,在C中可以使用B定义的
**template**
,在B中可以使用A定义的**template**
,但是C不能使用A定义的**template**
。
A template
B template
include
可以将目标文件除了
外的整个代码引入,相当于是拷贝到
include
位置,如:
body
header
footer
[setData](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/tips.html)
–>数据更新
setData
是小程序开发中使用最频繁的接口,也是最容易引发性能问题的接口。- 小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的
evaluateJavascript
所实现。即用户传输的数据,①需要将其转换为字符串形式传递
,②同时把转换后的数据内容拼接成一份 JS 脚本
,③再通过执行 JS 脚本的形式传递到两边独立环境
。- 而
evaluateJavascript
的执行会受很多方面的影响,数据到达视图层并不是实时的
setData
可以直接将数据加入data中;如果在data中已经有该值,则修改它有着创建+更新功能 但正常是用来更新
Page({
data: {posts: [],test: "测试数据",flag: true},
//更新
this.setData({posts: content})
})
在我们分析过的一些案例里,部分小程序会非常频繁(毫秒级)的去
setData
,其导致了两个后果:
- Android 下用户在滑动时会感觉到卡顿,操作反馈延迟严重,因为 JS 线程一直在编译执行渲染,未能及时将用户操作事件传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层;
- 渲染有出现延时,由于 WebView 的 JS 线程一直处于忙碌状态,逻辑层到页面层的通信耗时上升,视图层收到的数据消息时距离发出时间已经过去了几百毫秒,渲染的结果并不实时;
由
setData
的底层实现可知,我们的数据传输实际是一次evaluateJavascript
脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程,
当页面进入后台态(用户不可见),不应该继续去进行
setData
,后台态页面的渲染用户是无法感受的,另外后台态页面去setData
也会抢占前台页面的执行
事件是视图层到逻辑层的通讯方式
。- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches。
事件分为冒泡事件和非冒泡事件:
冒泡事件
:当一个组件上的事件被触发后,该事件会向父节点传递。非冒泡事件
:当一个组件上的事件被触发后,该事件不会向父节点传递。- WXML的冒泡事件列表:
类型 | 触发条件 | 最低版本 |
---|---|---|
touchstart | 手指触摸动作开始 | |
touchmove | 手指触摸后移动 | |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
touchend | 手指触摸动作结束 | |
tap | 手指触摸后马上离开 | |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 | 1.5.0 |
longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) | |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | |
animationstart | 会在一个 WXSS animation 动画开始时触发 | |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | |
animationend | 会在一个 WXSS animation 动画完成时触发 | |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 | 1.9.90 |
注
:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件
,如 form 的submit
事件,input 的input
事件,scroll-view 的scroll
事件,(详见各个组件)
bind
绑定
- 代码示例
//也可以加冒号分隔
//
开启小程序之旅
Page({
tapName: function(event) { console.log(event)}
})
- 如果用户点击这个 view ,则页面的
tapName
会被调用。- 此时,页面的
this.data.tapName
必须是一个字符串,指定事件处理函数名;如果它是个空字符串,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)- 自基础库版本 1.5.0 起,在大多数组件和自定义组件中,
bind
后可以紧跟一个冒号,其含义不变,如bind:tap
。基础库版本 2.8.1 起,在所有组件中开始提供这个支持。
catch
绑定:
- 除
bind
外,也可以用catch
来绑定事件。与bind
不同,catch
会阻止事件向上冒泡。- 代码示例:
outer view
middle view
inner view
- 例如在上边这个例子中,点击 inner view 会先后调用
handleTap3
和handleTap2
(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2
,点击 outer view 会触发handleTap1
。
- 自基础库版本 2.8.2 起,除
bind
和catch
外,还可以使用mut-bind
来绑定事件。一个mut-bind
触发后,如果事件冒泡到其他节点上,其他节点上的mut-bind
绑定函数不会被触发,但bind
绑定函数和catch
绑定函数依旧会被触发。- 换而言之,所有
mut-bind
是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响bind
和catch
的绑定效果- 例如在下边这个例子中,点击 inner view 会先后调用
handleTap3
和handleTap2
,点击 middle view 会调用handleTap2
和handleTap1
outer view
middle view
inner view
- 自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段
恰好相反
。需要在捕获阶段监听事件时,可以采用capture-bind
、capture-catch
关键字,后者将中断捕获阶段和取消冒泡阶段。- 在下面的代码中,点击 inner view 会先后调用
handleTap2
、handleTap4
、handleTap3
、handleTap1
outer view
inner view
如果将上面代码中的第一个capture-bind改为capture-catch,将
只触发handleTap2
。
outer view
inner view
如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。
- 表格:
属性 | 类型 | 说明 | 基础库版本 |
---|---|---|---|
type | String | 代表事件的类型 | |
timeStamp | Integer | 事件生成时的时间戳–页面打开到触发事件所经过的毫秒数 | |
target | Object | 触发事件的组件的一些属性值集合–触发事件的源组件 | |
currentTarget | Object | 当前组件的一些属性值集合–事件绑定的当前组件 | |
mark | Object | 事件标记数据 | 2.7.1 |
- 补充说明
- target
属性 | 类型 | 说明 |
---|---|---|
id | String | 事件源组件的id |
dataset | Object | 事件源组件上由data- 开头的自定义属性组成的集合 |
- currentTarget
属性 | 类型 | 说明 |
---|---|---|
id | String | 当前组件的id |
dataset | Object | 当前组件上由data- 开头的自定义属性组成的集合 |
说明
: target 和 currentTarget 可以参考上例中,点击 inner view 时,handleTap3
收到的事件对象 target 和 currentTarget 都是 inner,而 handleTap2
收到的事件对象 target 就是 inner,currentTarget 就是 middle
- 表格:
属性 | 类型 | 说明 |
---|---|---|
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
- 补充说明
- touches
touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。 表示当前停留在屏幕上的触摸点。
属性 | 类型 | 说明 |
---|---|---|
identifier | Number | 触摸点的标识符 |
pageX, pageY | Number | 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴 |
clientX, clientY | Number | 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴 |
- changedTouches
changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)
- 表格
属性 | 类型 | 说明 |
---|---|---|
detail | Object | 额外的信息 自定义事件所携带的数据,如表单组件的提交事件会携带用户的输入,媒体的错误事件会携带错误信息,详见组件定义中各个事件的定义。 |
- 原理:小程序开发框架的逻辑层使用
JavaScript
引擎为小程序提供开发者JavaScript
代码的运行环境以及微信小程序的特有功能。
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份
JavaScript
文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似ServiceWorker,所以逻辑层也称之为 App Service。
- 在
JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
- 增加
App
和Page
方法,进行程序注册和页面注册。- 增加
getApp
和getCurrentPages
方法,分别用来获取App
实例和当前页面栈。- 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
- 提供模块化能力,每个页面有独立的作用域。
注意:小程序框架的逻辑层并非运行在浏览器中,因此
**JavaScript**
在 web 中一些能力都无法使用,如**window**
,**document**
** 等。**该部分将
截取官方文档
并加以注解
在小程序中所有页面的路由全部由框架进行管理
- 框架以
栈
的形式维护了当前的所有页面。- 对于路由的
触发方式
以及页面生命周期函数
如下:
路由方式 | 页面栈表现 | 触发时机 | 路由前页面 | 路由后页面 |
---|---|---|---|---|
初始化 | 新页面入栈 | 小程序打开的第一个页面 | onLoad, onShow | |
打开新页面 | 新页面入栈 | 调用 API wx.navigateTo 使用组件 |
onHide | onLoad, onShow |
页面重定向 | 当前页面出栈,新页面入栈 | 调用 API wx.redirectTo 使用组件 |
onUnload | onLoad, onShow |
页面返回 | 页面不断出栈,直到目标返回页 | 调用 API wx.navigateBack 使用组件 用户按左上角返回按钮 |
onUnload | onShow |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 如果从没有 tabBar 的页面跳转至有tabBar 的页面就一定要用这个 ,而不是上面的,否则会报错 |
调用 API wx.switchTab 使用组件 用户切换 Tab |
各种情况请参考下表 | |
重启动 | 页面全部出栈,只留下新的页面 | 调用 API wx.reLaunch 使用组件 |
onUnload | onLoad, onShow |
- 代码示例:
wx.navigateTo({ //当前页面被隐藏,缓存在栈中,最多存放10个页面
url: "/pages/posts/post" //跳转的页面路径
})
wx.redirectTo({ //当前页面被销毁
url: "/pages/posts/post"
})
- Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):
当前页面 | 路由后页面 | 触发的生命周期(按顺序) |
---|---|---|
A | A | Nothing happend |
A | B | A.onHide(), B.onLoad(), B.onShow() |
A | B(再次打开) | A.onHide(), B.onShow() |
C | A | C.onUnload(), A.onShow() |
C | B | C.onUnload(), B.onLoad(), B.onShow() |
D | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
D(从转发进入) | A | D.onUnload(), A.onLoad(), A.onShow() |
D(从转发进入) | B | D.onUnload(), B.onLoad(), B.onShow() |
navigateTo
,redirectTo
只能打开非 tabBar 页面。switchTab
只能打开 tabBar 页面。reLaunch
可以打开任意页面。- 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
- 调用页面路由带的参数可以在目标页面的
onLoad
中获取。注意
:开发者可以使用getCurrentPages()
函数获取当前页面栈- 页面栈中最多存在
10
个
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过
[module.exports](https://developers.weixin.qq.com/miniprogram/dev/reference/api/module.html)
或者exports
才能对外暴露接口。
重点举例⼩程序中常⽤的布局组件 view,tex 等,现只举例部分,之后遇到觉得需要mark再写入,大部分可以看官方文档组件部分,便不太多赘述
- 在小程序中,通常使用
代替
作为容器来做布局
<view class="container">
<image class="avatar" src="/images/测试头像图片.jpg">image>
<text>Hello,洪jltext>
<view>
<text>开启小程序之旅text>
view>
view>
- ⽂本标签
- 只能嵌套text
- ⻓按⽂字可以复制(只有该标签有这个功能)–>selectable
- 可以对如:
空格回车
进⾏编码 -->decode
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
selectable | Boolean | false | ⽂本是否可选 |
decode | Boolean | false | 是否解码 |
普 通
- 图⽚标签,image组件
默认
宽度320px、⾼度240px,所以如果不进行宽高设置,不会进行自适应- ⽀持懒加载
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
src | String | 图⽚资源地址 | |
mode | String | scaleToFill |
图⽚裁剪、缩放的模式 |
lazy-load | Boolean | false | 图⽚懒加载 |
mode
模式列举:
模式 | 值 | 说明 |
---|---|---|
缩放 | scaleToFill | 不保持纵横⽐缩放图⽚,使图⽚的宽⾼完全拉伸⾄填满image 元素 |
缩放 | aspectFit | 保持纵横⽐缩放图⽚,使图⽚的⻓边能完全显⽰出来。 |
缩放 | aspectFill | 保持纵横⽐缩放图⽚,只保证图⽚的短边能完全显⽰出来 |
缩放 | widthFix | 宽度不变,⾼度⾃动变化,保持原图宽⾼⽐不变 |
裁剪 | top | 不缩放图⽚,只显⽰图⽚的顶部区域 |
裁剪 | bottom | 不缩放图⽚,只显⽰图⽚的底部区域 |
裁剪 | center | 不缩放图⽚,只显⽰图⽚的中间区域 |
裁剪 | left | 不缩放图⽚,只显⽰图⽚的左边区域 |
裁剪 | right | 不缩放图⽚,只显⽰图⽚的右边区域 |
裁剪 | top left 、top right 、bottom left 、bottom right |
不缩放图⽚,只显示值所指向区域 |
- 代码示例:
滑块
视图容器
。其中只可放置swiper-item组件,否则会导致未定义的行为。
- 代码示例
- 该轮播图代码效果预览:
可滚动视图区域。使用竖向滚动时,需要给scroll-view一个固定高度,通过 WXSS 设置 height。组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。
- 使用举例图
Lin UI
是基于 微信小程序原生语法 实现的组件库。遵循简洁,易用的设计规范。- 与其他组件库不同的是,除了提供基本的组件外,还会提供
wxs模块
、高级组件
、电商组件模块
等等。 例如,在电商项目里常用的SKU联动选择
,城市选择器
等[安装](https://doc.mini.talelin.com/start/)
过程可看官方文档:
- 打开小程序的项目根目录,执行下面的命令(如果使用了云开发,需要进入miniprogram文件夹下执行下面的命令)
npm init
/*注意事项
1.执行npm init进行初始化,此时会生成一个package.json文件,如果不进行npm init,在构建npm的时候会报一个错误:没有找到 node_modules 目录
2.不建议使用cnpm,这样会带来一些未知的错误。如果网络情况不佳,可以使用下面的命令行更换为淘宝源。
npm config set registry https://registry.npm.taobao.org */
2)继续执行下面的命令
npm install lin-ui
- 安装完成后在小程序需要点击
工具
–>构建 npm
才可以使用(所有npm引入的都需要这一步
)- 要使用
自定义组件
的话,需要在配置.json
文件中(可以在全局的也可以在页面的,作用域不同)注册,具体实现看下面示例
- 要使用
自定义组件
的话,需要在当前page页面.json文件中注册
//page.json
{
"usingComponents": {
"l-avatar":"/miniprogram_npm/lin-ui/avatar/index",
"组件名(可以自取,一般如果是linui,就l-xxx)":"构建后的路径--要具体到那个文件夹下的js"
}
}
- 使用:
/* pages/welcome/welcome.wxss */
//可以自己写样式类,加到组件上
.l-avatar{
margin-top: 160rpx;
}
- 在当前page页面.json文件中注册
{
"usingComponents": {
"l-icon":"/miniprogram_npm/lin-ui/icon/index"
}
}
- 使用
类似于网页的
localStorage
官方文档很详细,此处给出具体地址,翻阅文档即可
一些微信官方给出的组件,具体参数解释看文档,以下给出学习过程中代码示例
wx.showToast
代码示例:
wx.showToast({
//此处其实已经被修改完状态,才开始提示,所以要反过来
title: this.data.collected ? '收藏成功' : '取消收藏',
duration: 1000
})
wx.showModal
代码示例:
async onCollect(e) {
const result = await wx.showModal({
title: !this.data.collected ? '进行收藏' : '取消收藏',
})
if (!result.confirm) return; //点击取消退出
.......//点击确认后运行的代码
wx.showToast({
//此处其实已经被修改完状态,才开始提示,所以要反过来
title: this.data.collected ? '收藏成功' : '取消收藏',
duration: 1000
})
},
- 运行效果示例(两者并存的效果):
- wx.getBackgroundAudioManager–播放音乐
- 代码示例
const app = getApp() //此处keyi
onLoad: function (options) {
const mgr = wx.getBackgroundAudioManager()
this.data._mgr = mgr
// if(app.gIsPlayMusic) { 此处进入即默认播放
// mgr.src = this.data.postData.music.url
// mgr.title = this.data.postData.music.title
// }
mgr.onPlay(() => {
console.log("监听播放")
})
mgr.onPause(() => {
console.log("监听暂停")
})
}
/**
* 音乐播放
*/
onMusic() {
const mgr = this.data._mgr
if (this.data.isPlaying) {
mgr.pause()
app.gIsPlayMusicId = -1
} //当前播放状态如果为true则终止(stop())、pause()暂停
else {
mgr.src = this.data.postData.music.url //此处为播放
mgr.title = this.data.postData.music.title
app.gIsPlayMusicId = this.data._pid
}
this.setData({
isPlaying: !this.data.isPlaying
})
},
在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作
- 代码示例
// pages/movie-detail/movie-detail.js
onViewPost(e) { //相册功能(预览)
wx.previewImage({
urls: [images1,images2],
})
},
- 详见开发文档
使用时在app.json中进行配置即可,相关配置详情看全局配置文档,如果需要进行相应操作看官方文档
"tabBar": {
"selectedColor": "#333333",
"color": "#999999",
"borderStyle": "black",
"position": "top",
"list": [
{
"pagePath": "pages/posts/posts",
"text": "阅读",
"iconPath": "/images/tabBar/yuedu.png",
"selectedIconPath": "/images/tabBar/yuedu_1.png"
},
{
"pagePath": "pages/movies/movies",
"text": "电影",
"iconPath": "/images/tabBar/dianying_1.png",
"selectedIconPath": "/images/tabBar/dianying.png"
}
]
}
分为
应⽤⽣命周期
和⻚⾯⽣命周期
关于小程序前后台的定义和小程序的运行机制,请参考运行机制章节。
- 应用生命周期表
属性 | 类型 | 必填 | 说明 | 场景 | 最低版本 |
---|---|---|---|---|---|
onLaunch | function | 否 | 生命周期回调——监听小程序初始化。 | 小程序初始化完成时触发,全局只触发一次。参数也可以使用 wx.getLaunchOptionsSync | |
获取。 | |||||
onShow | function | 否 | 生命周期回调——监听小程序启动或切前台。 | 小程序启动,或从后台进入前台显示时触发。也可以使用 wx.onAppShow | |
绑定监听 | |||||
onHide | function | 否 | 生命周期回调——监听小程序切后台。 | 小程序从前台进入后台时触发。也可以使用 wx.onAppHide | |
绑定监听 | |||||
onError | function | 否 | 错误监听函数。 | 小程序发生脚本错误或 API 调用报错时触发。也可以使用 wx.onError | |
绑定监听 | |||||
onPageNotFound | function | 否 | 页面不存在监听函数。 | 小程序要打开的页面不存在时触发。也可以使用 wx.onPageNotFound | |
绑定监听。 | 1.9.90 | ||||
onUnhandledRejection | function | 否 | 未处理的 Promise 拒绝事件监听函数。 | 小程序有未处理的 Promise 拒绝时触发。也可以使用 wx.onUnhandledRejection | |
绑定监听 | 2.10.0 | ||||
onThemeChange | function | 否 | 监听系统主题变化 | 系统切换主题时触发。也可以使用 wx.onThemeChange | |
绑定监听 | 2.11.0 | ||||
其他 | any | 否 | 开发者可以添加任意的函数或数据变量到 Object |
||
参数中,用 this |
|||||
可以访问 |
- 代码示例:
App({
onLaunch (options) {
// Do something initial when launch.
},
onShow (options) {
// Do something when show.
},
onHide () {
// Do something when hide.
},
onError (msg) {
console.log(msg)
},
globalData: 'I am global data'
,
onPageNotFound(res) {
wx.redirectTo({
url: 'pages/...'
}) // 如果是 tabbar 页面,请使用 wx.switchTab
}
})
- 页面生命周期表
属性 | 类型 | 说明 |
---|---|---|
data | Object | 页面的初始数据 |
options | Object | 页面的组件选项,同 Component 构造器 中的 options ,需要基础库版本 2.10.1 |
onLoad | function | 生命周期回调—监听页面加载 |
onShow | function | 生命周期回调—监听页面显示 |
onReady | function | 生命周期回调—监听页面初次渲染完成 |
onHide | function | 生命周期回调—监听页面隐藏 |
onUnload | function | 生命周期回调—监听页面卸载 |
onPullDownRefresh | function | 监听用户下拉动作 |
onReachBottom | function | 页面上拉触底事件的处理函数 |
onShareAppMessage | function | 用户点击右上角转发 |
onShareTimeline | function | 用户点击右上角转发到朋友圈 |
onAddToFavorites | function | 用户点击右上角收藏 |
onPageScroll | function | 页面滚动触发事件的处理函数 |
onResize | function | 页面尺寸改变时触发,详见 响应显示区域变化 |
onTabItemTap | function | 当前是 tab 页时,点击 tab 时触发 |
其他 | any | 开发者可以添加任意的函数或数据到 Object 参数中,在页面的函数中用 this 可以访 问 |
- 官方的小程序页面生命周期图:
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似
这部分将截取文档自定义组件部分中常见的部分进行注解
类似于页面,自定义组件拥有自己的
wxml
模板和wxss
样式。
组件对应
wxss
文件的样式,只对组件wxml内的节点生效。编写组件样式时,需要注意以下几点:
- 组件和引用组件的页面不能使用id选择器(
#a
)、属性选择器([a]
)和标签名选择器,请改用class选择器。- 组件和引用组件的页面中使用后代选择器(
.a .b
)在一些极端情况下会有非预期的表现,如遇,请避免使用。- 子元素选择器(
.a>.b
)只能用于view
组件与其子节点之间,用于其他组件可能导致非预期的情况。- 继承样式,如
font
、color
,会从组件外继承到组件内。- 除继承样式外,
app.wxss
中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)。
#a { } /* 在组件中不能使用 */
[a] { } /* 在组件中不能使用 */
button { } /* 在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */
除此以外,组件可以指定它所在节点的默认样式,使用
:host
选择器(需要包含基础库 1.7.2 或更高版本的开发者工具支持)。注:此处本人出了一个
问题
,详见—>本笔记的杂记->初学者阶段遇到的问题与解决->Ⅶ
- 有时,组件希望接受外部传入的样式类。此时可以在
Component
中用externalClasses
定义段定义若干个外部样式类。这个特性可以用于实现类似于view
组件的hover-class
属性:页面可以提供一个样式类,赋予view
的hover-class
,这个样式类本身写在页面中而非view
组件的实现中。
注意:在同一个节点上使用普通样式类和外部样式类时,两个类的
**优先级是未定义**
的,因此最好避免这种情况。
- 代码示例:
- 自定义组件部分定义与占位符示例
/* 组件 custom-component.js */
Component({
externalClasses: ['my-class']
})
<!-- 组件 custom-component.wxml 如何引用 -->
<custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>
这样,组件的使用者可以指定这个样式类对应的 class ,就像使用普通属性一样。在 2.7.1 之后,可以指定多个对应的 class 。
- 外部使用自定义组件并传入样式类
<!-- 页面的 WXML -->
<custom-component my-class="red-text" />
<custom-component my-class="large-text" />
<!-- 以下写法需要基础库版本 2.7.1 以上 注意 这只是一个组件传入两个类名,而不是分别创建两个组件-->
<custom-component my-class="red-text large-text" />
------------ 样式类声明 页面.wxss ---------------------------------
.red-text {
color: red;
}
.large-text {
font-size: 1.5em;
}
- 主要用途:
- 如果子组件都是我们自己开发的,而且无所谓改动自定义组件源码,那可以不使用这个
- 如果自定义组件封装已经足够成熟,不想再动其中样式源码,就可以用外部样式类进行对自定义组件样式改变(使用
!important
属性能将样式优先级提高),以此进行对于封装好的组件的样式修改,同理可以运用于第三方库
.movielist{ //外部样式类
margin-bottom: 25rpx;
background-color: #fff !important; //此处就可以将这个样式提升到自定义组件样式优先级之上
}
- 以后如果自己封装自定义组件,就可以向外暴露外部样式类
组件间的基本通信方式有以下几种。
- WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。具体在 组件模板和样式 章节中介绍。
- 事件:用于子组件向父组件传递数据,可以传递任意数据。
- 如果以上两种方式不足以满足需要,父组件还可以通过
this.selectComponent
方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。
自定义组件触发事件时,需要使用
triggerEvent
方法,指定事件名、detail对象和事件选项
- 官方代码示例
<!-- 在自定义组件中 -->
<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
//js文件中
Component({
properties: {},
methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
- 本人在
[hello小程序](https://gitee.com/hongjilin/wechat-applet-demo-source-code)
源码中应用
<!--pages/posts/posts.wxml-->
<block wx:for="{{posts}}" wx:for-item="item" wx:key="postId" wx:for-index="index">
<post bind:posttap="onGoDetail" res="{{item}}" />
</block>
// components/posts/index.js 这是自定义组件
methods: {
onTap (e) { //此处不能用箭头函数,否则` this.triggerEvent`将会找不到报错
const pid = this.data.res.postId
// console.log( this.data)
// console.log( this.properties)
this.triggerEvent('posttap',{
pid //这个参数会在事件调用处获取到
})
},
}
// pages/posts/posts.js 这个是在调用自定义组件的页面的js中,即可以使用自己的方法,单纯是调用自定义组件定义的事件
onGoDetail: (e) => { //获取组件的自定义属性
//先判断,如果e.currentTarget.dataset去得到值,就取有值的 下面这3种写法效果等同
// let pid = (e.currentTarget.dataset.id)?e.currentTarget.dataset.id:e.detail.pid
// let pid = e.detail.pid|e.currentTarget.dataset.id
let pid = e.detail.pid || e.currentTarget.dataset.id
wx.navigateTo({
url: '/pages/post-detail/post-detail?pid=' + pid,
})
体系学习过程笔记外的知识点
- 本技巧适用于
微信开发者工具
- 当你需要新建一个页面时:新建一个page文件目录–>右键
新建page
–>输入page名字–>一次生成所需四个文件 且自动注册到app.json
中- ##如果配置文件中出现错误时,自动新建无法成功,更无法自动注册
当你写多个page时,如果每次通过修改
app.json
的配置项来指定初始页面,十分麻烦
- 可以在
app.json
用"entryPagePath":“pages/页面文件夹/页面文件名” 配置首页,但仍要修改配置文件,十分麻烦- 使用编译器的
工具栏
–>添加编译模式
进行指定初始化页面(启动页面默认值要先删除才有提示)
- 添加后每次调试只要
选择编译模式
,就可以切换初始页面
只能调成字体了,
这个BUG被修复了
学习、练习、开发微信小程序过程中遇到的一些基础知识与细节记录
/
代表根目录:如引入根目录下的images/图片
<image src="/images/测试头像图片.jpg">image>
- 其余的如:
../
上一级目录、./
同级目录,都与一般无异
安装第三方库后在小程序需要点击
工具
–>构建 npm
才可以使用
所有npm引入的都需要这一步
这部分将记录本人初学小程序过程遇到的问题,这部分应该大部分是小程序初学者才会遇到的,或者是本人虽然可以直接解决但觉得别人可能会遇到的便记录下来。而后续进阶阶段或者实战开发时遇到的问题,将记录在下面另一章节
- 解决:可以在你需要修改的page的样式文件中,给
标签加样式,默认小程序是使用作为最外层的
page{
background-color: #b3d4db;
}
原⽣⼩程序不⽀持 less ,其他基于⼩程序的框架⼤体都⽀持,如 wepy , mpvue , taro 等。 但是仅仅因为⼀个less功能,⽽去引⼊⼀个框架,肯定是不可取的。因此可以⽤以下⽅式来实现
"less.compile": {
"outExt": ".wxss"
}
- 在要编写样式的地⽅,新建 less ⽂件,如 index.less ,然后正常编辑即可。
TypeError: wx.getMenuButtonBoundingClientRect is not a function
控制台报错:
TypeError: wx.getMenuButtonBoundingClientRect is not a function
问题分析:这个 api是 更高版本版本支持的,你的用户有的客户端基础库版本 小于这个基础库。你在小程序后台设置下 最低基础库2.1.0.那样用户客户端基础库版本低于此就会提示升级
无效的page.json
这是初学者才会犯下的错误,但也记录下来
typeError: Cannot read property 'mark' of undefined
- 报错
- 解决:最终发现是小程序工具设置问题
- 问题代码截图:
- 问题分析:
众所周知,箭头函数
会改变this指向
,当我使用箭头函数后,函数中的this不再指向实例而是指向函数本身,导致data其实是找不到的发生报错
- 问题解决:
- 不使用箭头函数:
async onCollect(e) {
const result = await wx.showModal({
title: !this.data.collected ? '进行收藏' : '取消收藏',
})
if (!result.confirm) return;
let postCollected = this.data._postCollected //将当前data中(相当于之前本地缓存的postCollected)拉去下来,防止被覆盖
postCollected[this.data._pid] = !this.data.collected
this.setData({
collected: !this.data.collected
})
wx.setStorageSync('posts_collected', postCollected)
wx.showToast({
//此处其实已经被修改完状态,才开始提示,所以要反过来
title: this.data.collected ? '收藏成功' : '取消收藏',
duration: 1000
})
},
- 使用箭头函数,但需要保存this指向
let con //用来保存this指向
Page({
//1. 生命周期函数中保存this指向
onLoad: function (options) {
con=this //用来保存this指向
},
//2. 函数体写法
onCollect:async (e)=> { 箭头函数写法,需要保存this指向
console.log(con)
const result = await wx.showModal({
title: !con.data.collected ? '进行收藏' : '取消收藏',
})
if (!result.confirm) return;
let postCollected = con.data._postCollected //将当前data中(相当于之前本地缓存的postCollected)拉去下来,防止被覆盖
postCollected[con.data._pid] = !con.data.collected
con.setData({
collected: !con.data.collected
})
wx.setStorageSync('posts_collected', postCollected)
wx.showToast({
//此处其实已经被修改完状态,才开始提示,所以要反过来
title: con.data.collected ? '收藏成功' : '取消收藏',
duration: 1000
})
})
Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
- 出现场景:在我将之前写好的样式模块抽出成
自定义组件
时,控制台突然出现警告
- 分析:我使用了
属性选择器
,而官方文档在自定义组件部分有要求不能使用,防止出现样式错误,
- 解决:将属性选择器删除即可
flex布局 justify-content:space-between; 解决最后一排数量不够自动向两端排列问题
- 问题图示:
- 分析:flex 布局两端对齐当最后一排数量不够时,会出现以下布局情况
- 解决方法1:父级添加after伪类法
ps:这种解决方案只适合每列有
3个
的分布情况,如果布局每列有4个,5个,就需要解决方法2
- 解决方法2:使用grid栅格布局,此处不详解,只将解决方案指出,有需要的直接百度搜索
使用grid栅格布局
即可