小程序和传统的网页的区别:
1、开发环境不同,网页运行在浏览器环境中,小程序运行在微信环境中。
2、无法使用浏览器的API 如Dom,BOM,但是可以使用微信环境中的提供的API.
3、开发模式不同:传统:浏览器+代码、小程序(注册账号、使用开发工具、创建和配置)
创建一个小程序
1、注册账号,省略
开发选择
其中,TS是一种强类型化面向对象的编译语言,JS是一种轻量级的解释型语言。
1、TypeScript
2、JavaScript
3、Ts(TypeScript)+Less(Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充。Less 可以运行在 Node 或浏览器端。)
一、目录结构
nimiprogram ------------------项目名称
|----pages------------------------------模块总汇
|--------index--------------------------模块名
|------------index.json---------------局部配置(该文件的页面配置文件,影响范围也仅限当前页面)
|------------index.ts------------------相当于 javascript ,和js文件功能一致。小程序逻辑(该页面的页面逻辑,这个文件里的逻辑只针 对当前页面,不会影响到别的页面;)
|------------index.wxml-------------相当于html(该页面的布局文件,相当于html文件,描述的是页面的结构)
|------------index.wxss-------------相当于局部css(该页面的样式表,相当于css,描述的是当前页面的样式)
|----utils
|----app.json --------小程序公共配置
|----app.ts
|----app.wxss
|----sitemap.json
|----typings
|----.eslintrc.js
|----project.config.json
|----project.private.config.json
|----tsconfig.json
配置文件是以.json 结束的,小程序中总共有4种配置文件。
二、创建小程序的页面
只要在app.json的路径中添加页面的存放路径,就会自动生成目。 注意在小程序的app.json中,"pages"路径中谁第一个,谁就是首页,即和顺序有关系。
三、WXML和HTML的区别
四、WXSS和CSS的区别
五、小程序中js文件的分类
六、小程序宿主环境包含的内容
1)、通信模型
1、通信的主体
小程序中通信的主题是渲染层和逻辑层,其中:
① WXML模板和WXSS样式工作在渲染层
②js脚本工作在逻辑层
2)、运行机制
3)、组件
小程序中的组件也是由宿主环境提供的,开发者可以基于组件快速搭建出漂亮的页面结构。官方把小程序的组
件分为了9大类,分别是:
1、视图容器
1)View: 普通的视图区域,类似HTML中的div,是一个块级元素,常用来实现页面的布局效果。
text 标签 文字容器,相当于span, 而且同一个view中,text标签内容不换行。
2)scroll-view:可滚动的视图区域,常用来实现滚动列表效果。
3)swiper和swiper-item
轮播图容器组件 和 轮播图item组件
:nth-child(n) /* 选择第n个,n位数字 */
swiper的常用属性
2、基础内容
2.1 text 文本组件,类似HTML中的span标签。text标签内容不换行
在小程序里面只有text组件的selectable属性,可以实现常按选中文本复制功能。
2.2 rich-text 富文本组件,支持把HTML字符串渲染为WXML结构
通过rich-text组件的nodes属性节点,把HTML字符串渲染为对应的UI结构。
3、其他常用的组件
1) button
2)image
图片控制使用mode属性
3)navigator
4)、API
小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,例如:获取用户信息、本地存储、支付功能等。
七、WXML模板语法-数据绑定
1、数据绑定的基本原则
1)在data中定义数据 在js文件中。
2)在WXML中使用数据
使用Mustache语法(双打括号将变量包裹起来即可),也叫插值法,应用场景如下:
绑定内容: {{ 变量}},
绑定属性:
运算(三元运算、算术运算等):
三元运算:
算术运算:
八、事件绑定
小程序中常用的事件,使用bind绑定事件
当事件回调出发的时候,会收到一个事件对象event, 它的详细属性如下表所示:
target是触发该事件的源头组件,而currentTarget则是当前事件所绑定的组件。举例如下:
8.1 bindtap的语法格式
在小程序中,不存在HTML中的onclick鼠标点击事件,而是通过tap事件来响应用户的触摸行为。
在js中和data平级,函数名(){}, 的格式。
8.1.1、 在事件处理函数中为data中的数据赋值
通过**this.setData(dataObject)**方法, 可以给页面data中的数据重新赋值。
8.1.2、事件传参
小程序中的事件传参比较特殊,不能在绑定事件的同时为事件处理函数传递参数。data-* ={{ 变量 }} 如果不加双括号,那么传递的文本字符串。
在事件处理函数中,通过event.target.dataset.参数名 即可获取到具体参数的值。
8.2 bindput的语法格式
8.3、实现文本框 和 data之间的数据同步
定义数据
染结构
美化样式
绑定input事件处理函数,根据input传递的值来改变原始的定义的值。
九、条件渲染
在小程序中,使用wx:if=“{{condition}}” 来判断是否需要渲染该代码块。
<view wx:if="{{ condition }}"> True </view>
也可以使用wx:elif 和 wx:else 来添加else判断:
block标签(不是组件,它只是一个包装元素;它不会在页面中做任何的渲染,它只接收控制属性) ,如果要一次性控制多个组件的展示和隐藏,可以使用block标签。
<view wx:if="{{ type === 1}}">男</view>
<view wx:elif="{{ type === 2}}">女</view>
<view wx:else>保密</view>
<!--或者使用block标签,渲染成功后只输出文本文字,而上面会输出<view>保密</view>等字样-->
<block wx:if="{{ type === 1}}">男</block>
<block wx:elif="{{ type === 2}}">女</block>
<block wx:else> 保密</block>
view标签(是一个组件,它可以在页面上做渲染) 相当于html 中的div
text 标签 文字容器,相当于span, 而且同一个view中,text标签内容不换行
hidden 标签 隐藏或者显示
wx:if 与 hidden 的对比
<view hidden="{{!statusTag}}">我出来了~</view>
<button bind:tap="showIt">显示</button> <!--绑定事件,使用bind:tap-->
<button bind:tap="hiddenIt">隐藏</button>
ts中的代码
showIt:function(){
this.setData({statusTag : true})
},
hiddenIt:function(){
this.setData({statusTag: false})
}
block的使用
<block wx:if={{ true }} >
...
</block>
<block wx:elif={{...}}>
...
</block>
<block wx:else>
...
</block>
十、列表渲染
wx:for对应的是要循环的那个数组(必选),使用Mustache语法,即双大括号。
wx:for-index对应的是循环数组的索引值(下标)
wx:for-item对应循环数组中的每一项
wx:key 表示的数组的唯一值(必选) 也建议为渲染出来的列表指定唯一的key值,从而提高渲染的效率。key值不用加{{}}。 一般使用数据中的id,如果没有id,那么就使用索引 index来代替。
html代码:
<view wx:for="{{input_data}}" wx:for-item="items" wx:key="index">
<block>{{items.unique}}</block>
</view>
<text>-------------------------------------------------------------------------</text>
<input value="{{item.id}}" wx:for="{{input_data}}" name="test" wx:key="unique" />
<text>-------------------------------------------------------------------------</text>
js代码:
data: {
input_data: [
{ id: 1, unique: "unique1" },
{ id: 2, unique: "unique2" },
{ id: 3, unique: "unique3" },
{ id: 4, unique: "unique4" },
]
},
修改默认的wx:for-index对应的是循环数组的索引值(下标),wx:for-item对应循环数组中的每一项。
<view wx:for="{{input_data}}">
<view> {{ index }} ---{{ item.unique}}</view>
</view>
<text>--------------------修改默认的index和item----------------------------------</text>
<view wx:for="{{input_data}}" wx:for-index="ids" wx:for-item="UserName">
<view> {{ ids }} ---{{ UserName.unique }}</view>
</view>
js/ts中的data 数据 this.setData({…});
// 获取应用实例,返回当前项目的实例,
const app = getApp<IAppOption>();
//或者是
const app = getApp();
Page({
//页面的初始数据
data: {},
//生命周期函数--监听页面加载
onLoad() {},
//生命周期函数--监听页面初次渲染完成
onReady() {},
//生命周期函数--监听页面显示
onShow() {},
//生命周期函数--监听页面隐藏
onHide() {},
//生命周期函数--监听页面卸载
onUnload() {},
//页面相关事件处理函数--监听用户下拉动作
onPullDownRefresh() {},
//页面上拉触底事件的处理函数
onReachBottom() {},
//用户点击右上角分享
onShareAppMessage() {}
//也可以加入自定义函数
setUserName(){
console.log('我执行了');
console.log(this); //打印了整个js的方法
console.log(this.data);
//获取某个对象的值
console.log(this.data.obj.name);
//修改值
this.data.obj.name = 'lmb'; //只是修改,无法完成直接渲染
//如果想修改的时候,直接在页面上渲染显示
this.setData({ "obj.name":'lmb' }); //固定写法
}
})
9、配置文件 app.json.
每一个小程序页面也可以使用同名 .json
文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json
的 window
中相同的配置项。
{
//定义了所有页面的路由
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/birds/index"
],
//主体颜色
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
//定义了全局的tabBar
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页"
}, {
"pagePath": "pages/logs/logs",
"text": "日志"
}]
},
"style": "v2",
//搜索引起
"sitemapLocation": "sitemap.json"
//定义启动页,首页
"entryPagePath": "pages/logs/logs",
}
十一、wxss 模板样式
wxss具有css大部分特性,同时,wxss还对css进行了扩充以及修改,以适应微信小程序的开发。
与css相比,wxss扩展的特性有:
1、rpx尺寸单位
2、@import 样式导入
1)rpx(responsive pixel) 是微信小程序独有的,用来解决屏幕适配的尺寸单位。
2)rpx 与 px 之间的单位换算
3)使用@import导入公共的样式表
相对路径,封号结束。
@import "/common/common.css";
4)全局样式 和 局部样式
全局样式: 根目录下的app.wxss 作用于所有的的页面
局部样式: 每个页面自己的wxss( 即pages/xxx/xxx.wxss). 只作用于当前的页面
鼠标放在css的选择器上,就会出现权重。
十二、全局配置
app.json或者其他页面的.json文件中。里面的属性有很多,可以参考:
1、windows属性:
window节点常用的配置项:
设置步骤: app.json-> window -> navigation… 颜色只支持#开头
2、tabBar 底部tab栏的表现
其中list的必选的,其他的都是可选项。而在list数组中,每个数组又有哪些属性那?
图片资源可以放在根目录的images中。
十三、局部配置
1、就是每个页面中的.json配置文件。用来对当前的窗口外观、页面效果等进行配置。
2、如果某些小程序页面想要拥有特殊的窗口表现,此时,“页面级别的.json配置文件” 就可以实现这种效果。
而且这些属性直接赋值,不用放在window下。
十四、网络请求
1、小程序中网络数据请求的限制
2、配置request合法域名
3、发起GET请求
实例:
4、发起POST求情
5、在页面刚加载时请求数据
就是在加载页面的时候调用函数,可以放在js中的onLoad中。
6、跳过request 合法域名校验
7、关于跨域和Ajax的说明
十五、页面导航(超链接)
1、声明式导航
1) 导航到tabBar页面
tabBar 页面指的是被配置为 tabBar 的页面。
在使用 组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:
●url 表示要跳转的页面的地址,必须以 / 开头
●open-type 表示跳转的方式,必须为 switchTab 同时也可以进行参数传递,
● 参数与路径之间使用 ? 分隔
● 参数键与参数值用 = 相连
● 不同参数用 & 分隔
<navigation url="/pages/index/index" open-type="switchTab">导航到首页</navigation>
<!--传递参数-->
<navigation url="/pages/index/index?name=20&age=30" open-type="switchTab">导航到首页</navigation>
2)导航到非tabBar页面
非 tabBar 页面指的是没有被配置为 tabBar 的页面。
在使用 组件跳转到普通的非 tabBar 页面时,则需要指定 url 属性和 open-type 属性,其中:
● url 表示要跳转的页面的地址,必须以 / 开头
● open-type 表示跳转的方式,必须为 navigate (默认也是navigate, 所有可以省去open-type)
示例代码如下:传参方式同上
<navigation url="/pages/info/info" open-type="navigate">导航到info页面</navigation>
注意:为了简便,在导航到非 tabBar 页面时,open-type=“navigate” 属性可以省略。
3)后退导航
如果要后退到上一页面或多级页面,则需要指定 open-type 属性和 delta 属性,其中:
● open-type 的值必须是 navigateBack,表示要进行后退导航
● delta 的值必须是数字,表示要后退的层级
示例代码如下:
<navigator open-type='navigateBack' delta='1'>返回上一页</navigator>
注意:为了简便,如果只是后退到上一页面,则可以省略 delta 属性,因为其默认值就是 1。
2、编程式导航
1) 导航到tabBar页面
调用 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面。其中 Object 参数对象的属性列表如下:
代码实例:
传参代码:
2)导航到非tabBar页面
调用 wx.navigateTo(Object object) 方法,可以跳转到非 tabBar 的页面。其中 Object 参数对象的属性列表如下:
实例代码:传参方式同上
3)后退导航
调用 wx.navigateBack(Object object) 方法,可以返回上一页面或多级页面。其中 Object 参数对象可选的属性列表如下:
代码实例:
3、参数获取
通过声明式导航传参或编程式导航传参所携带的参数,可以直接在 onLoad 事件中直接获取到,示例代码如下:
//结束的参数如何在其他方法中使用
data: {
query:{}
},
OnLoad: function(options){
this.setData({
query:options
})
}
十六、页面事件
1、下拉刷新
下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为。
启用下拉刷新有两种方式:
①全局开启下拉刷新
● 在 app.json 的 window 节点中,将 enablePullDownRefresh 设置为 true
②局部开启下拉刷新
● 在页面的 .json 配置文件中,将 enablePullDownRefresh 设置为 true
在实际开发中,推荐使用第 2 种方式,为需要的页面单独开启下拉刷新的效果。
③配置下拉刷新窗口的样式
在全局或页面的 .json 配置文件中,通过 backgroundColor 和 backgroundTextStyle 来配置下拉刷新窗口的样式,其中:
● backgroundColor 用来配置下拉刷新窗口的背景颜色,仅支持16 进制的颜色值
● backgroundTextStyle 用来配置下拉刷新 loading 的样式,仅支持 dark 和 light
④在页面的 .js 文件中,通过 onPullDownRefresh() 函数即可监听当前页面的下拉刷新事件。
例如,在页面的 wxml 中有如下的 UI 结构,点击按钮可以让 count 值自增 +1:
在对应的js文件中有onPullDownRefresh 方法
data: {
count:0
},
onPullDownRefresh() {
this.setData({
count: this.data.count +1
})
},
⑤停止下拉刷新的效果
当处理完下拉刷新后,下拉刷新的 loading 效果会一直显示,不会主动消失,所以需要手动隐藏下拉刷新的 loading 效果。此时,调用 wx.stopPullDownRefresh() 可以停止当前页面的下拉刷新。示例代码如下:
data: {
count:0
},
onPullDownRefresh() {
this.setData({
count: this.data.count +1
})
wx.stopPullDownRefresh()
},
2、上拉触底事件
上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为。
在页面的 .js 文件中,通过 onReachBottom() 函数即可监听当前页面的上拉触底事件。示例代码如下:
上拉触底距离指的是触发上拉触底事件时,滚动条距离页面底部的距离。
可以在全局或页面的 .json 配置文件中,通过 onReachBottomDistance 属性来配置上拉触底的距离。
小程序默认的触底距离是 50px,在实际开发中,可以根据自己的需求修改这个默认值。
扩展运算符用三个点号表示,功能是把数组或类数组对象展开成一系列用逗号隔开的值. 适用于加载更多内容,代码如下:
//随机颜色函数
getColors(){
wx.showLoading({
title: '数据加载中',
})
wx.request({
url: 'https://www.escook.cn/api/color',
method: 'GET',
success: ({data: res})=>{
this.setData({
colorList: [...this.data.colorList, ...res.data]
})
},
complete:()=>{
wx.hideLoading()
}
})
},
对上拉触底进行节流处理: 其实就是通过一个变量来控制是否在执行任务,如果没有则这行,否则上划无效
使用节流的步骤
①在 data 中定义 isloading 节流阀
● false 表示当前没有进行任何数据请求
● true 表示当前正在进行数据请求
②在 getColors() 方法中修改 isloading 节流阀的值
● 在刚调用 getColors 时将节流阀设置 true
● 在网络请求的 complete 回调函数中,将节流阀重置为 false
③在 onReachBottom 中判断节流阀的值,从而对数据请求进行节流控制
● 如果节流阀的值为 true,则阻止当前请求
● 如果节流阀的值为 false,则发起数据请求
十七、生命周期
生命周期函数:是由小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行。
生命周期函数的作用:允许程序员在特定的时间点,执行某些特定的操作。例如,页面刚加载的时候,可以在 onLoad 生命周期函数中初始化页面的数据。
注意:生命周期强调的是时间段,生命周期函数强调的是时间点。
1)应用的生命周期函数:
2)页面的生命周期函数
十八、wxs脚本/模块
WXS(WeiXin Script)是小程序独有的一套脚本语言,结合 WXML,可以构建出页面的结构。
wxml 中无法调用在页面的 .js 中定义的函数,但是,wxml 中可以调用 wxs 中定义的函数。因此,小程序中 wxs 的典型应用场景就是“过滤器”。
位置: 写在wxml文件或者wxs文件中。
在wxml中使用, 不管是wxs文件,还是在wxml中的代码块,都是一个独立的模块。他内部变量与函数,默认为私有的。
一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports
实现
wxs 和 JavaScript 的关系*****
1、内嵌wxs脚本
实例2
<!--实例1-->
<wxs module="m1"> <!--m1为模块名-->
var msg = "hello world";
module.exports.message = msg;
</wxs>
<!--直接调用-->
<view> {{m1.message}} </view>
----------------------------------------------------------------------------------------------------------
<!--实例2-->
<wxs module="util">
module.exports.include=function(listid,id){
return listid.indexOf(','+id,",")>1
}
<!--上述写法等价于-->
<!--
module.exports={
include : function(listid,id){
return listid.indexOf(','+id,",")>1;
}
}
-->
</wxs>
<!--直接调用-->
<view style="height: {{height}}px; background-color: rgb(25, 143, 137); width: 140rpx; position: fixed; left: 0;">
<view wx:for="{{count}}" wx:key="index" class="normal {{util.include(listid,index+1)?'sel':''}}" bindtap="click" data-id="{{index+1}}">类型{{index+1}}</view>
</view>
2、定义外联的wxs脚本
在 wxml 中引入外联的 wxs 脚本时,必须为 标签添加 module 和 src 属性,其中:
- module 用来指定模块的名称
- src 用来指定要引入的脚本的路径,且必须是相对路径
示例代码如下:
在common.wxs文件中(在wxxml中需要导入后在使用)
var foo = "'hello world' from comm.wxs";
var bar = function(d) {
return d;
}
//输出两个模块
module.exports = {
foo: foo,
bar: bar
};
module.exports.msg = "some msg";
在wxml中调用
<wxs src="common.wxs" module="tools" /> <!--导入并自定义模块名 为tools-->
<view> {{tools.msg}} </view>
<view> {{tools.bar(tools.foo)}} </view>
十九、自定义组件 components
一、创建组件
二、引用组件
1、局部引用
要在使用的页面的json文件中的usingComponents 使用 键值对 进行引用。
2、全局引用
三、全局引用 VS 局部引用
四、组件和页面的区别
五、自定义组件的样式
1、组件样式隔离
2、组件样式隔离的注意点
3、 修改组件的样式隔离选项
默认情况下,自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题。但有时,我们希望在外界能够控制组件内部的样式,此时,可以通过 styleIsolation 修改组件的样式隔离选项(组件js中根节点中添加options:{ styleIsolation: ‘isolated’}),用法如下:
styleIsolation的可选值
六、自定义组件 - 数据、方法和属性
1、data数据
2、methods方法
3、properties属性
实例,在test组件的js文件中的properties中定义,用来接收外界传递过来的参数
//有两种方式,一是简化方式,二是 完整方式
//1 简化方式
max: Number
//2 完整的定义方式‘
max:{
type: Number, //数组类型
value: 10 //默认值
}
使用:
//1、首先在全局引用,在app.json或者页面中的json文件中引用 既"usingComponents":{"mytest":"/components/test/test"}
<!--引用完以后 在mxml中使用-->
<mytest max = "9" ></mytest>
4、组件中data 和 properties 的区别
5、使用 setData 修改 properties 的值
七、数据监听器
1. 什么是数据监听器
2. 数据监听器的基本用法
在js中的和methods同级, observers中监听属性,如果有变化,即触发。
3、监听对象属性的变化
数据监听器支持监听对象中 单个 或者 多个属性的变化。
4、监听对象中所有属性的变化
/**
* 组件的初始数据
*/
data: {
rgb:{ //创建rgb颜色对象,有3个属性
r:0,
g:0,
b:0
},
fullColor:'0,0,0' //创建字符串
},
/**
* 组件的方法列表
*/
methods: {
changR(){
this.setData({
//给对象的属性赋值
'rgb.r': this.data.rgb.r + 5 > 255? 255 : this.data.rgb.r + 5
})
},
changG(){
this.setData({
//给对象的属性赋值
'rgb.g': this.data.rgb.g + 5 > 255? 255 : this.data.rgb.g + 5
})
},
changB(){
this.setData({
//给对象的属性赋值
'rgb.b': this.data.rgb.b + 5 > 255? 255 : this.data.rgb.b + 5
})
}
},
observers:{
//后面的参数,分别为对应的前面三个变量的最新值
/*
'rgb.r,rgb.g,rgb.b':function (r,g,b) {
this.setData({
//用反单引号凭借变量,中间的变量使用${变量名}
fullColor: `${r},${g},${b}`
})
}
*/
// 上述如果参数太多,写起来很麻烦,可以使用通配符来实现
'rgb.**':function(object){
this.setData({
fullColor:`${object.r},${object.g},${object.r}`
})
}
}
wxml代码
<view style="background-color: rgb({{fullColor}});" class="colorBox">
颜色值:{{fullColor}}
</view>
<button size="mini" bindtap="changR" type="default">R</button>
<button size="mini" bindtap="changG" type="default">G</button>
<button size="mini" bindtap="changB" type="default">B</button>
5、自定义组件的纯数据字段
1)什么是纯数据字段
如上述的grb对象,页面中没有调用,只是在内部使用,就可以定义为纯数据字段。
2)使用规则
将属的代码进行改进
options:{
//指定所有_开头的数据字段为纯数据字段
pureDataPattern: /^_/
}
/**
* 组件的初始数据
*/
data: {
_rgb:{ //创建rgb颜色对象,有3个属性
r:0,
g:0,
b:0
},
fullColor:'0,0,0' //创建字符串
},
八、自定义组件的生命周期
如何定义组件的生命周期函数?
lifetimes 节点
在小程序组件中,生命周期函数可以直接定义在 Component 构造器的第一级参数中,可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)。示例代码如下:
九、组件所在页面的生命周期
pageLifetimes 节点
组件所在页面的生命周期函数,需要定义在 pageLifetimes 节点中,示例代码如下:
使用实例: 需要在进入使用组件的页面,生成一个随机的颜色,修改我们默认的黑色。
思路:就是在组件所在的页面的生命周期show的时候,生成并赋值。
/**
* 组件的方法列表
*/
methods: {
changR(){
this.setData({
//给对象的属性赋值
'_rgb.r': this.data._rgb.r + 5 > 255? 255 : this.data._rgb.r + 5
})
},
changG(){
this.setData({
//给对象的属性赋值
'_rgb.g': this.data._rgb.g + 5 > 255? 255 : this.data._rgb.g + 5
})
},
changB(){
this.setData({
//给对象的属性赋值
'_rgb.b': this.data._rgb.b + 5 > 255? 255 : this.data._rgb.b + 5
})
},
// 随机生成RGB颜色的方法。
_randomColor(){
this.setData({
_rgb:{
r:Math.floor(Math.random() * 256),
g:Math.floor(Math.random() * 256),
b:Math.floor(Math.random() * 256)
}
})
}
},
pageLifetimes:{
show:function () {
//console.log("show")
//页面展示的时候就开始赋值
this._randomColor()
},
hide:function () {
console.log("hide")
}
}
十、自定义组件的插槽
2、单个插槽
在小程序中,默认每个自定义组件中只允许使用一个 进行占位,这种个数上的限制叫做单个插槽。
实例: 我们先建立一个组件,然后在app.json配置文件中使用"usingComponents": { “test4”:“/components/test4/test4”}
组件的内容如下:
在页面中使用
// components/test4/test4.js
Component({
options:{
//启用多个slot
multipleSlots:true
},
....
})
使用多个slot 实例: 在组件的wxml中
<view>
<!--定义了两个插槽,使用名字来识别-->
<slot name="before"></slot>
<view>这里是组件的内部结构</view>
<slot name="after"></slot>
</view>
在页面中使用此组件
在使用带有多个插槽的自定义组件时,需要用 slot 属性来将节点插入到不同的 中
<test4>
<view slot="before">我是前面的</view>
<view slot="after">我是后面的</view>
</test4>
十一、父子组件之间的通信
1)、属性绑定
属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传递给子组件。父组件的示例代码如下:
需要在子组件在 properties 节点中声明对应的属性并使用。
在组件中先定义要接收的属性名,在组件的js文件中的 properties中注册,指定类型或者给个值都可以
通过页面开始传递属性
在插件中显示,看是否传递成功
2)、事件绑定
结合我们上述的例子,进行代码实例演示:
首先调用子组件的页面(父组件)定义个一个函数 syncCount(){…},然后在通过引用子组件的时候传递给子组件。
在子组件的js中,通过this.triggerEvent(‘自定义时间名称’,{/参数对象/}),将数据发送到父组件。
3)、获取组件的形式实现父子组件通讯
4、自定义组件的behaviors
在组件中使用behavior。 使用之前需要先引入,在组件的js中引入。
const myBehavior = require('../../behaviors/my-behavior')
使用behavior中的定义的值,在组件的wxml中调用。
组件和模块不同,他是一组文件,文件结构上和一个页面相同(包括wxml,wxss,js,json),组件相当于一个模块中的一个小模块(页面),包含了完整的wxml,wxss,js,json模块
建议自动生成,里面的js,json和普通page不一样。js页面如下: component中,方法都必须放在methods中,组件用的初始化数据放在data中,需要由父类(调用此组件的wxml或component文件)传递的值放在properties中。其他文件的编写和页面一致。
behavior中所有可用的节点
同名字段的覆盖和组合规则
二十、使用npm包
1、npm,Node Package Manager的缩写,也就是“节点的包管理器”。
顾名思义,npm是一个软件包管理器,主要进行JAVAScript的包管理。通过npm,我们可以很方便地进行JavaScript包的下载、升级,我们也可以把我们开发的JavaScript包共享给其他使用者。
我们可以简单地把npm当成一个JavaScript语言的Maven,使用起来非常方便。
2、vant weapp组件使用
1、先看是否有包管理配置文件,如果没有需要创建。
参考: https://vant-contrib.gitee.io/vant-weapp/#/quickstart#bu-zou-san-xiu-gai-project.config.json
安装插件
npm i @vant/weapp -S --production
使用插件 在项目的app.json中添加引用组件
使用之前,将原来的 “style”: “v2”, 给删除掉,样式冲突。 按需导入。
"usingComponents": {
"van-button":"@vant/weapp/button/index",
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
3、定制全局主体样式:
Vant Weapp使用css变量来实现定制主题。关于css变量的基本用法,请参考MDN文件:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties
定义的是要注意作用域,下面定义的作用域是html,如果定义为
/* 作用域在局限在container1中 */
.container1{
--main-color:#C00000;
}
/* 如果想让整个页面都其作用,那么定义在根节点上,既html */
html{
--main-color:#C00000;
}
在小程序中如何定制自己的主体样式,在app.wxss中,写入css变量,即可对全局生效:如果是全局,那么变量需要放在page下
page{
--button-danger-background-color:#C00000;
--button-danger-border-color:#D60000;
}
变量名参数:
https://github.com/youzan/vant-weapp/blob/dev/packages/common/style/var.less
4、基于回调函数的异步API的缺点
API Promise优化
API Promise****化,指的是通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性,避免回调地狱的问题。
然后在终端窗口进行安装:
安装完毕后需要构建,然后才能使用。每次构建的时候,先需要删除miniprogram_npm这个目录(进入目录后,强制删除)。然后在点击开发工具中的 工具-构建NPM
构建完成后,我们会在miniprogram_npm中看到以前安装的和刚安装的第三方法包
构建完毕后,开始使用Promise。在app.js中导入
// 通过es6语法,按需导入,导入promisifyAll() 方法,即可实现异步API的promise化
import {promisifyAll} from 'miniprogram-api-promise'
//该方法需要两个参数, wx:(是微信的顶级对象,包含了很多方法)
//将微信的 wx 的中的方法进行promisifyAll化,然后在挂载到wxp中。
const wxp = wx.p = {}
promisifyAll(wx,wxp)
调用Promise化之后的异步API( 不用在使用回调函数了)
/*
getInfo(){
// 返回值为promise对象
const res = wx.p.request({
url: 'https://www.escook.cn/api/get',
method:'GET',
data:{name:'zs',age:20}
})
console.log(res)
*/
//在进一步优化
async getInfo(e){
// 将data 重命名为res
const {data:res} = await wx.p.request({
url: 'https://www.escook.cn/api/get',
method:'GET',
data:{name:'zs',age:20}
})
console.log(res)
},
二十一、全局数据共享
全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。开发中常用的全局数据共享方案有:Vuex、Redux、MobX 等。
推荐使用Vuex
小程序中的全局数据共享方案
使用两个包来完成,mobx-miniprogram 和 mobx-miniprogram-bindings来实现的,二者功能不同。
使用步骤:
1、安装Mobx相关的包
在小程序的目录列表右键-在外部终端窗口打开
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
主要安装完后,要删除项目根目录miniprogram_npm目录,然后在重建。
2、创建 MobX 的 Store 实例
2.1、在项目根目录下创建一个store目录,在目录中创建store.js 文件。
// 在这个 js文件中,专门来创建Store的实例对象
//1、导包 es6语法 import {要使用的方法1、要使用的方法2} from
import { observable,action } from 'mobx-miniprogram'
//使用es6的导出语法 observable返回值就是store的实例,外界在需要的时候,可以导入这个实例,利用里面的数据。
export const store = observable({
//初始化的参数
//数据字段
numA:1,
numB:2,
//计算属性 get是修饰符,表示只读属性,只能获取,不能赋值
get sum(){
return this.numA + this.numB
},
//需要导入action 方法,用来修改store中的数据. 外部无法修改store,只能通过调用store内部方法来实现数值的修改。
updateNum1:action(function(step){
this.numA += step
}),
updateNum2:action(function(step){
this.numB += step
}),
})
2.2 在页面中使用
使用前,需要将Store中的成员绑定到页面的js文件中。
1)在页面的js中导入我们安装的mobx-miniprogram-bindings, 和 我们创建的Store对象(导入2个)。
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
2)在页面的js中的onLoad中绑定
createStoreBindings 两个参数,第一个是要绑定到哪个的页面(this);第二个参数是一个page对象,包含了3个属性(store,fields,actions)store 数据源,fields需要用到哪些字段,actions需要用到哪些方法。
onLoad(options) {
this.storeBindings = createStoreBindings(this,{
store,
fields:['numA','numB','sum'],
actions:['updateNum1','updateNum2']
})
},
3)在页面的js中的onUnload中卸载
onUnload() {
this.storeBindings.destroyStoreBindings()
},
4)在页面的wxml中使用
<view>{{numA}} + {{numB}} = {{sum}}</view>
<lmb_buttom type="danger" bindtap="getInfo1" data-step="{{1}}">自加1</lmb_buttom>
<lmb_buttom type="primary" bindtap="getInfo2" data-step="{{-1}}">自减1</lmb_buttom>
在js中定义方法
getInfo1(e){
this.updateNum1(e.target.dataset.step)
console.log(e.target.dataset.step)
},
getInfo2(e){
this.updateNum2(e.target.dataset.step)
console.log(e.target.dataset.step)
},
2.3 在组件中使用全局数据共享
1、在组件的js文件中,导包(2个包)
2、构behaviors数组 和 storeBindings对象(并加入属性)
3、在组件的页面中就可以直接调用数据或方法了。
//storeBindingsBehavior相当于桥梁,专门负责将store里面的数据或成员映射到当前的组件中来
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store'
Component({
//建behaviors数组,将import导入的storeBindingsBehavior直接放入数组中,要通过他来实现方法和数据的映射。通过storeBindingsBehavior 来实现自动绑定
behaviors:[storeBindingsBehavior],
//声明一个page对象,里面有3个属性。
storeBindings:{
store,
fields:{
numA:() => store.numA, //绑定字段的第1种方式
numB:(store) =>store.numB, //绑定字段的第2种方式
sum:'sum' //绑定字段的第3种方式
},
actions:{//指定要绑定的方法
updateNum2:'updateNum2'
}
},
/**
* 组件的方法列表
*/
methods: {
getInfo1(e){
this.updateNum2(e.target.dataset.step)
console.log(e)
},
getInfo2(e){
this.updateNum2(e.target.dataset.step)
console.log(e)
}
},
二十二、 分包
分包的概念
1. 什么是分包
分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
2. 分包的好处
对小程序进行分包的好处主要有以下两点:
● 可以优化小程序首次启动的下载时间
● 在多团队共同开发时可以更好的解耦协作
3. 分包前****项目的构成
4. 分包后****项目的构成
5. 分包的加载规则
6. 分包的体积限制
如何分包
只要在app. json中添加配置, 保存,就会自动创建目录。
"subpackages":[
{
//第一个分包
"root":"packageA", //所在的根目录
"name":"p1", //别名,可以不加
"pages":[
"pages/cat/cat",
"pages/dog/dog",
]
},
{
//第二个分包
"root":"packageB",
"name":"p2",
"pages":[
"pages/cat2/cat2",
"pages/dog2/dog2",
]
}
]
查看分包的大小:
右上角-详情-基本信息
打包的原则
独立分包
独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而单独运行。
独立分包 和 普通分包的区别
独立分包的应用场景:
开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:
● 当小程序从普通的分包页面启动时,需要首先下载主包
● 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度
注意:一个小程序中可以有多个独立分包。
独立分包的设置
和设置分包操作一样,唯一不同的是,在页面下设置 “independent”:true
独立分包的引用原则
独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源。
分包预下载
分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度。
配置分包预下载
分包预下载的限制:
同一个分包中的页面享有共同的预下载大小限额 2M,例如:
二十三、模板使用
使用的方法和页面的模板一样,都是通过import来实现的。可以在根目录下建立一个文件夹,放置局部的css和html模板。如果其他页面需要可以直接调用,这样就不会影响到全局。
1、创建模板
一般建立一个template的文件夹,里面放置很多模板,通过子文件夹名称来识别,每个模板有2个文件(wxml和wxss)
2、定义模板:
位置/template/goods/下
<template name="goodList">
...
</template>
<template name="title">
...
</template>
3、使用模板:
<import src="../template/goods.wxml">
<view>
<template is="title"></template>
<template wx:for="{{[1,2,3,4,5]}}" wx:key="index" is="goodList"></template>
</view>
样式就是写一个普通的css文件,在需要的地方,使用
@import "../..";
导入想把某个页面全部导入使用,使用include标签
<include src="....wxml">
import标签只能导入template模板内容,而include标签导入非template标签。
wxs文件共享
wxs文件是由微信小程序内部转换成可执行的js文件。
在根目录下建立wxsJs/demo4.wxs
var title = "商品列表";
var list = [1,2,3,4];
module.exports={
title:title,
list:list
}
使用,在wxml文件中直接引用
<!--引入一个wxs文件,module变量,相当于将引入的文件全部变量都放在这个变量中-->
<wxs src="../../wxsJs/demo4.wxs" module="data"></wxs>
<!--访问-->
{{data.title}}
{{data.list}}
我们在定义个js文件,路径为wxsJs/title.wxs
var title = "商品列表";
module.exports = {
title:title
}
如果刚才建立的js文件想使用这个定义,方法如下:
var title = require(./title.wxs); //此处的title是对象
var list = [1,2,3,4];
module.exports={
title:title.title,
list:list
}
二十四、自定义tabBar
自定义 tabBar 分为 3 大步骤,分别是:
先安装第三方插件,vant-weapp组件. 安装完毕后需要重新构建。如果根目录下以前存在miniprogram_npm目录,需要先删除掉,然后在构建。
①配置信息
在app.json中引入组件
"tabBar": {
"custom": true, //启用自定义tabBar,但是原始的代码也不能删除,如果出现不兼容等现象会调用此代码。
"color": "",
"selectedColor": "#000000",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}],
"usingComponts":{}
},
"usingComponents": {
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
将原有的tabBar保留,在根节点加一个属性,“custom”: true,
②添加 tabBar 代码文件
在项目的根目录下建立一个文件夹,名为custom-tab-bar, 在其内建立一个index组件。文件夹的名称和组件的名称是固定的,不能修改。
③编写 tabBar 代码
在组件的wxml代码,会自动显示到首页的底部。
我们使用vant-weapp组件,进行布局tabBar,将代码直接拷贝到index.wxml中,然后在进行调整距离和菜单的图标等。
index.wxml
<van-tabbar active="{{ active }}" bind:change="onChange">
<!--自己定义的图片-->
<van-tabbar-item info='3' wx:for="{{list}}" wx:key="index">
<image slot="icon" src="{{ item.iconPath }}" mode="aspectFit" style="width: 25px; height: 25px;" />
<image slot="icon-active" src="{{ item.selectedIconPath }}" mode="aspectFit" style="width: 25px; height: 25px;" />
{{ item.text}}
</van-tabbar-item>
<!--系统提供的样式-->
<van-tabbar-item info="3">
<image slot="icon" src="{{ icon.normal }}" mode="aspectFit" style="width: 30px; height: 18px;" />
<image slot="icon-active" src="{{ icon.active }}" mode="aspectFit" style="width: 30px; height: 18px;" />
自定义
</van-tabbar-item>
<!--系统提供的没有图标的tab-->
<van-tabbar-item icon="friends-o">标签</van-tabbar-item>
<van-tabbar-item icon="setting-o">标签</van-tabbar-item>
</van-tabbar>
index.js
// custom-tab-bar/index.js
Component({
/**
* 修改组件的样式和page样式的关联,否则会出现修改css无法正常显示
*/
options:{ styleIsolation:'shared' },
/**
* 组件的初始数据
*/
data: {
active: 0,
icon: {
normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
active: 'https://img.yzcdn.cn/vant/user-active.png',
},
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}],
},
/**
* 组件的方法列表
*/
methods: {
onChange(event) {
// event.detail 的值为当前选中项的索引
console.log(event)
this.setData({ active: event.detail });
},
}
})
详细步骤,可以参考小程序官方给出的文档:
https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html
其他知识点集合
1、js 中的逻辑运算符
真前假后
false||? 返回?
true||? 返回true
只要“||”前面为Flase,不管“||”后面是true还是false,都返回“||”后面的值。
只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。
假前真后
false&&? 返回flase
true&&? 返回?
只要“&&”前面为Flase,不管“&&”后面是true还是false,都返回“&&”前面的值。
只要“&&”前面为true,不管“&&”后面是true还是false,都返回“&&”后面的值。
2、text-shadow属性的语法:
text-shadow: h-shadow v-shadow blur color;
h-shadow: 设置水平阴影的位置(x轴方向),必需要设置的参数;允许负值。
v-shadow : 设置垂直阴影的位置(y轴方向),必需要设置的参数,允许负值。
blur: 阴影模糊的距离(半径大小),可选择设置的参数。
color : 阴影的颜色,可选择设置的参数。
bbar-item>
index.js
```js
// custom-tab-bar/index.js
Component({
/**
* 修改组件的样式和page样式的关联,否则会出现修改css无法正常显示
*/
options:{ styleIsolation:'shared' },
/**
* 组件的初始数据
*/
data: {
active: 0,
icon: {
normal: 'https://img.yzcdn.cn/vant/user-inactive.png',
active: 'https://img.yzcdn.cn/vant/user-active.png',
},
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "信息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "联系我们",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}],
},
/**
* 组件的方法列表
*/
methods: {
onChange(event) {
// event.detail 的值为当前选中项的索引
console.log(event)
this.setData({ active: event.detail });
},
}
})
详细步骤,可以参考小程序官方给出的文档:
https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html