选中一段文字 或 什么东西 ctrl+d 快速选择下一个 可以快速替换
高度坍塌 父元素无法撑起子元素
在父元素添加:after伪类{
选中父元素的最后面
content:"";
添加空白
display:block;
为块元素
clear:both;
清楚浮动
}
一个页面四部分组成 不产生样式冲突
shift+alt+F 格式化代码
view等于div
<scroll-view class="box" scroll-x> 包裹view盒子
<swiper class="container1"
indicator-dots 激活小圆点
indicator-color="pink" 小圆点未激活颜色
indicator-active-color="lightgoldenrodyellow"小圆点激活颜色
autoplay 自动播放
interval='5000' 自动播放的间隔时间
circular 轮播图衔接滚动
>
<swiper-item>
<view class="item">
A
</view>
</swiper-item>
<swiper-item>
<view class="item">
B
</view>
</swiper-item>
<swiper-item>
<view class="item">
C
</view>
</swiper-item>
</swiper>
text组件 支持文本长按选中效果
<text>长按选中文本text</text>
rich-text 富文本 渲染wxhtml标签 外面是双引号 里面是单引号 不能出一点错误
<rich-text nodes="<h1 style='color: pink;'>我爱你</h1>"></rich-text>
3.
正常
<button>普通按钮</button>
<button type="primary">按钮</button>
<button type="warn">按钮</button>
尺寸
<button size="mini">按钮</button>
<button type="primary" size="mini">按钮</button>
<button type="warn" size="mini">按钮</button>
镂空
<button size="mini" plain>按钮</button>
<button type="primary" size="mini" plain>按钮</button>
<button type="warn" size="mini" plain>按钮</button>
app.json 下面的 style :"v2"还是v3 设置其设定的样式
图片是image mode设置其图片大小的模式 aspectFill 方面的纵横比填充 aspectFit 纵横缩小
WightFix 宽度填满 高度拉长 heightFix 相反
<image src="../images/11.webp" mode="" mode="aspectFill"/>
4.mustache 语法
<view>
{{uname}} {{password}}
</view>
<!-- <image src="{{info}}" mode=""/> -->
{{ran}}
<view>
{{ran>=5 ? "我是帅哥" : "贱货差我"}}
</view>
事件
target:触发该事件的源头组件
currentTarget是当前事件的组件
e.target 是内部的组件
e.currentTarget是当前的view组件
事件处理 eventHandler
<button type="primary" bindtap="btnTapHandler">点我</button> {{num}}
btnTapHandler(e){
console.log(e);
// 当前的设置data属性方法 : 需要设置的属性: 访问属性是 this.data.属性
this.setData({
num: this.data.num+1
})
}, 一定要加逗号
在事件的传参里,传参的值不能直接写到括号里面
data-info="{{}}" info是参数的名字 2是参数值
<button bindtap="btnHandler" data-info="{{2}}">
e.datail.value是变化过后的新值 绑定其值
5.
<button type="primary" bindtap="btnTapHandler">点我</button> {{num}}
<button type="primary" bindtap="chuanCan" data-info="{{2}}">事件传参</button>
<input value="{{msg}}" bindinput="inputHandler"> </input>
this.setData({
// 因为e.detail.value是属性变化后的新值 将其值 不断的赋予其值就可以实现数据绑定
msg:e.detail.value
})
6.<!-- 条件渲染 判断其type的值 来决定其显示和隐藏 -->
判断data中的type的值 来判断其if的显示和隐藏
<view wx:if="{{type===1}}">
男
</view>
<view wx:elif="{{type===2}}">
女
</view>
<view wx:else>
傻逼
</view>
7.
block标签只是包裹效果 不会起到任何作用
<block wx:if="{{false}}">
8.
hidden="condition" 属性也可以显示和隐藏
false代表激活显示 不执行hidden效果 ture代表隐藏
二者等同于 vue的v-if和v-show
wx:if是动态创建和移除元素的方式
hidden是切换样式:display:block/none
频繁切换是hidden 条件复杂是wx:if
9.
<!-- for列表渲染 -->
wx:for-item指定渲染的名称 wx:for="{{名称}}" wx:key="id" 提高渲染的性能
这里是指定其for-item和key的自定义名称
key的值需要与其遍历的id值 其index的会
<view wx:for="{{arr1}}" wx:for-item="xiang" wx:key="id">
{{index}} {{xiang.id}}{{xiang.name}}{{xiang.age}}
</view>
arr1:[
{id:1,name:"艾璟",age:18},
{id:2,name:"艾璟",age:18},
{id:3,name:"艾璟",age:18},
],
10.导入 @import 后面跟需要导入的外联表的相对路径;
exmple:@import "/common/common.wxss";
/直接写路径 代表直接进入其指定的文件夹下
11.window的配置项
navigationBarTitleText 导航的名称 dark whilt
navigationBarTextStyle 导航的颜色 #16进制的
navigationBarBackgroundColor 导航的背景颜色
backgroundTextStyle 导航的文本颜色 只有黑白
enablePullDownRefresh: true, 全局开启下拉刷新
backgroundColor: "#efefef" 下拉刷新空间的颜色
onReachBottomDistance 下拉触底加载 最好别射
12.tabBar 最少2个 最多5个 在app.json中写
backgroundColor 背景颜色
selectedIconPath 已选中图标的路径显示
selectedColor 选中的颜色
borderStyle 边框样式
iconPath 未选中的图标
color 颜色
Must 这里是定义其tabBar的基本属性 只能由5个tabBar 而非tabBar可以通过函数指定
list 必填属性 Array类型:
pagePath 必填 页面路径 在pages中预先定义
text 必填 tab上面显示的文字
iconPath 不必填 未选中的图标路径 position为top不显示icon
selectedIconPath 不必填 选中时的图标样式 position为top不显示icon
example: 例子
"tabBar": {
"list":[
{
"pagePath": "pages/index/index",
"text": "index"
},
{
"pagePath": "pages/test/test",
"text": "test"
}
]
},
12.request域名
域名支持https://
预备不能使用ip地址和localhost
要icp备案
一个月最多申请5次
get请求
wx.request({
url:"https://www.excook.cn/api/get",
method:"GET", //请求的方式 get和post
data:{ //发生到服务器的数据
name:"aijing",
age:22
},
success:(res)=>{ //请求成功返回的回调函数
console.log(res)
}
})
警告不显示:在project.config.json下的 添加 checkSiteMap:false
导航到tabBar页面
tabBar指被配置为tabBar 的页面
在navigator组件跳转到指定的tabBar页面 需要指定url属性和open-type=switchTab
url:跳转的页面地址 必须以/开头
open-type:跳转的方式 必须是switchTab
什么叫非tabBar的页面:是值在app.JSON中 在tabBar中已经定义的页面
"tabBar": {
"list":[
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "./common/images/公积金.png",
"selectedIconPath": "./common/images/关注.png"
},
{
"pagePath": "pages/test/test",
"text": "测试",
"iconPath": "./common/images/历史.png",
"selectedIconPath": "./common/images/更多.png"
}
]
},
而在非tabBar中跳转是
在navigator中指定url和open-type
url 地址以 /开头
open-type:是navigate 其实跳转到非tabBar页面 open-type=“navigate”可以不写
后退导航 open-type="navigateBack"后退一层 delta默认为1 可以不写 默认退一层
<navigator open-type="navigateBack" delta="1">back</navigator>
13.编程式导航跳转tabBar页面
wx.switchTab(Object object)方法 跳转到 tabBar页面 Object对象参数列表
url string 必填 需要跳转到tabBar页面的路径 路径后不带参数
// 编程式导航跳转到tabBar页面
tiaoIndex(){
wx.switchTab({
url:"/pages/index/index",
})
},
14.编程式导航跳转非tabBar页面 必须是没有定义在tabBar中的页面 定义的跳不了
wx.navigateTo(Object,object)
url:地址 必填 在url的后面可以跟参数 ?参数名称=参数项&连接
15.后退导航
button bintap='gotoback'
gotoBack(){
wx.navigateBack()
}
如果要多层退出
wx.navigateBack({
delta:层数
})
16.导航传参 :就是在跳转到其页面时 传递其页面所需要的参数
直接在路径的后面加参数 路径和参数用?分隔 参数键和参数值用=连接 不同的参数用&分隔
navigator url="/page/info/info?name=aijing&age=18
17.接收导航传输的参数是
通过声明式或编程式导航传参的参数 在onLoad事件中获取
onLoad:function(options){
}
18. 导航传参的参数打印出来 声明一个对象 保存传递过来的值
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log(options);
this.setData({
query:options
})
},
19.全局下拉刷新和局部下拉刷新
全局里面 app.json的window节点中 enablePullDownRefresh 为true
局部 页面的json中 enablePullDownRefresh 为 true
backgroundColor 下拉刷新背景颜色
backgroundTextStyle dark和light 是下拉刷新的圆点样式
在onPullDownRefresh()函数中 监听当前页面下拉所执行
20. 在下拉刷新设置count的值清零
<view>我是count{{count}}</view>
<button bindtap="countAdd">count加1</button>
countAdd(){
this.setData({
count:this.data.count+1
})
},
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.setData({
count:0
})
},
21.停止下拉刷新的效果
处理完后下拉刷新的loading效果一直显示 不会主动消失
wx.stopPullDownRefresh()停止效果
直接写在下拉刷新的 函数下面就可以
22.监听页面的上拉触底事件
当页面滑到最下面 需要加载页面
onReachBottom() 监听上拉触底
节流:在同一时间只允许处理一次请求 当第一次请求未处理完之前 不允许执行第二次请求
23.配置上拉触底的距离:触发时,滚动条距离页面底部的距离
在json文件中 onReachBottomDistance 配置需求的页面底部距离
24.
第一步:解构赋值 获取颜色
data: {
colorList:[]
},
getColors(){
wx.request({
url: 'https://www.escook.cn/api/color',
method:"GET",
// 解构赋值
success:({data:res})=>{
console.log(res);
this.setData({
// data:res指定获取res里面的data
// colorList:[...this.data.colorList,...res.data]
两个都可以给colorList数组赋值 第二个是数组concat方法
// 将data的colorList和获取的数据连接colorList:this.data.colorList.concat(res.data)
})
}
})
},
第二步: 循环 添加样式
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color:rgba({{item}});">9:40 2023/4/20
{{item}}
</view>
.num-item{
border: 1px solid #efefef;
border-radius: 8rpx;
line-height: 250rpx;
margin: 15rpx;
text-align: center;
text-shadow: 0rpx 0rpx 5rpx #fff;
box-shadow: 1rpx 1rpx 6rpx #aaa;
}
第三步:
onReachBottom() {
// 在上拉触底时调用其获取颜色的方法 实现二次请求
this.getColors();
},
第四步:
在getColor方法里面在发起请求之前先提示加载效果
// 需要展示loading效果
wx.showLoading({
title: '数据加载中...',
})
与发起请求的success平级 请求完成之后隐藏其效果
complete:()=>{
wx.hideLoading()
}
第五步:节流 分三步
首先:在data中定义isloading节流阀
false没有进行任何请求
true正在请求
其次:在getColors()方法中修改isloading节流阀的值
在刚调用getColors将节流阀设置true
在请求complete回调函数中,节流阀重置为false
最后:在onReachBottom中判断节流阀的值 请求数据进行节流控制
节流阀为true 阻止请求
为false 发起请求
完整的js
data: {
colorList:[],
isloading:false,//false是没有请求 true是正在发起请求
},
getColors(){
this.setData({
isloading:true//刚开始发起请求
}),
// 需要展示loading效果
wx.showLoading({
title: '数据加载中...',
})
wx.request({
url: 'https://www.escook.cn/api/color',
method:"GET",
// 解构赋值
success:({data:res})=>{
console.log(res);
this.setData({
// data:res指定获取res里面的data
colorList:[...this.data.colorList,...res.data]
// colorList:this.data.colorList.concat(res.data)
})
},
complete:()=>{
wx.hideLoading()
this.setData({
isloading:false//请求结束后 加载隐藏 节流阀关闭请求
})
}
})
},
onReachBottom() {
if(this.data.isloading) return //判断其请求的值
// 在上拉触底时调用其获取颜色的方法 实现二次请求
this.getColors();
},
25.自定义编译模式 :在保存刷新后 刷新的是你定义的页面 而不是一直是首页了 热加载 提高开发效率
26.life cycle
生命周期函数:小程序框架提供的内置函数 伴随生命周期 自动按次序执行
其function:允许程序员在特定的时间点,执行特定的操作 :像在页面刚加载onload的时候 初始化页面的数据
生命周期强调的是时间段 生命周期函数强调的是时间点
27.小程序的应用生命周期函数在app.js中进行声明
分为前台和后台:前台是页面运行 后台是在后台运行
onLaunch 运行 全局只触发一次
onShow 显示
onHide 切后台 运行
28.页面的生命周期函数 .js
Page({
onLoad(){ 监听页面加载 一个页面只触发一次
}
onShow(){ 监听页面显示
}
onReady(){ 页面的初次渲染完成 一个页面只触发一次
}
onHide(){ 页面隐藏
}
onUnload(){ 页面卸载 一个页面只触发一次
}
})
29.wxs是小程序的脚本语言
wxml中无法调用页面的.js中定义的函数 但是在wxml中可以调用wxs中wxs中定义的函数 wxs典型应用在过滤器中
wxs有自己的number string boolean object function array date regexp
不支持es6以上语法 let const 解构赋值等
遵循 CommonJS规范
module对象 require()函数 module.exports对象
<!-- wxs脚本 -->
<view>
其使用wxs的函数 :wxs文件module名称.导出的函数(括号里面是在函数处理)
{{m1.toUpper(username)}}
</view>
<wxs module="m1">
这是第一种 先写函数 再导出export
function toUpper(str){
return str.toUpperCase()
}
module.exports={
toUpper:toUpper
}
这是第二种 直接导出指定的函数
module.exports.toUpper=function(str){
return str.toUpperCase()
}
</wxs>
在utils文件夹下新建 tools.wxs文件:
//外部wxs脚本文件
// 函数 str形参 返回形参的小写
function toLower(str){
return str.toLowerCase()
}
// 导出其函数
module.exports={
// 属性对应值
toLower:toLower
}
这里使用的话就是 tools.toLower()函数
在外部wxml引入外联的wxs脚本 必须为<wxs module='' src=''></wxs>
module是指定模块的名称
src是指定要引入脚本路径 必须是相对路径
<view>
{{m2.toLower(country)}}
</view>
<!-- 导入外联的wxs文件 -->
module为指定的名称 调用时要 指定的名称.导出的函数名称
<wxs src='../../utils/tools.wxs' module="m2"></wxs>
30.九宫格 点击跳转到对应的页面shoplist 显示其内容 每一个九宫格对应一个页面 在点击的时候对每一个页面指定的内容进行渲染
<view class="grid-list">
<!-- 将整个九宫格变成导航navigator组件 每一个跳转到shoplist里面传递其id值和标题值 -->
<navigator class="grid-item" wx:for="{{gridList}}" wx:key="id" url="/pages/shoplist/shoplist?id={{item.id}}&title={{item.name}}">
<image src="{{item.icon}}"></image>
<text>{{item.name}}</text>
</navigator>
</view>
如果要在一个页面的onLoad 和OnReady中使用相同的内容 就在data中定义数据 在data中的数据是当前页面所有函数共享的
我们都知道 在加载的时候options这个形参里面 存放着传递过来的参数 就可以把上面传递过来的参数 赋值到data中的query
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
query:options
})
},
获取到传递过来的参数 存到query中
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
// 只有在onReady里面调用这个方法 来动态设置其九宫格对应的标题
wx.setNavigationBarTitle({
title: this.data.query.title,
})
},
setNavigationBarTitle()这个方法是改变顶部的标题
列表页面的api接口
https://www.escook.cn/categories/:cate_id/shops
:cate_id是动态参数 表示分类的id
请求参数:
_page是请求第几页的数据
_limit是每一页请求多少条数据
判断是否还有下一页的数据
公式:页码值*每页显示多少条数据>=总数据条数
page*pageSize>=total
如果一共有77条数据 每页10条 分为8页 一页7条
7*10>=77
31.组件
新建一个文件 右键新建components—新建一个组件
全局配置组件 在app.json中定义
"usingComponents": {
"my-test1":"/components/test/test"
}
不行的话就重启小程序
32.在组件的js文件下 的Component里面 定义 外面的样式进不来组件
在组件和引用组件的页面中建议使用class选择器 不要使用id,属性,标签选择器
// 启用样式隔离
options:{
styleIsolation:'isolated'
},
isolated:启用样式隔离 在自定义组件内外 使用class选择器不会影响
apply-shared属性值代表外界可以影响到组件中 组件中写的样式 在外面不会有影响 单向绑定
shared 代表 双向影响 外界影响里面 组件也影响外界 互通就像双向绑定
33.自定义方法 +1之后 提示框加1
addCount(){
this.setData({
count:this.data.count+1
})
this._showCount()
},
// 下划线的函数 代表我不是通过手指来触摸的
_showCount(){
wx.showToast({
title: 'count的值是'+this.data.count,
icon:"none"
})
}
!!!!
data是存储组件的私有数据
properties是存储外界传递到组件的数据
showInfo(){
console.log(this.data);
console.log(this.properties);
console.log(this.data===this.properties);
},
在组件中的properties就像props定义
/**
* 组件的属性列表 外界传递的数据
*/
properties: {
max: {
type: Number,
value: 1
}
},
data和properties是一模一样的但是使用方式不同
console.log(this.data);
console.log(this.properties);
if(this.data===this.properties)
{
console.log('Niu');
}
两者一模一样 但是使用方式不同
我也可以在properties中定义数据 来在this.setData()方法中改变值
也可以修改properties中的数据
!!!数据监听器: 只能在组件中使用
observe数据的监听器 监听数据的新值和旧值
案例:
n1+n2等于sum和
<view>
{{n1}}+{{n2}}={{sum}}
</view>
<button bindtap="addN1">n1+1</button>
<button bindtap="addN2">n2+1</button>
// 数据的监听器 watch 对象的形式
observers:{
这里是新值n1和新值n2 给其结果加上最新的n1+n2的结果
'n1,n2'(newN1,newN2){
this.setData({
sum:newN1+newN2
})
}
},
34.在this.setData(方法中不仅可以直接写data中的数据 还可以是对象.属性的解构 定义对象的某个属性的值)
<view>
第三个案例--颜色改变
<view class="rgb" style="background-color: rgb({{fullColor}});">
{{fullColor}}
</view>
<button bindtap="changeR" type="default">R</button>
<button bindtap="changeG" type="warn">G</button>
<button bindtap="changeB" type="primary">B</button>
<view>
{{rgb.r}}{{rgb.g}}{{rgb.b}}
</view>
</view>
// 第三个案例 改变颜色
changeR(){
this.setData({
'rgb.r':this.data.rgb.r+this.data.seize>=255? 255:this.data.rgb.r+this.data.seize
})
},
changeG(){
this.setData({
'rgb.g':this.data.rgb.g+this.data.seize>=255? 255:this.data.rgb.g+this.data.seize
})
},
changeB(){
this.setData({
'rgb.b':this.data.rgb.b+this.data.seize>=255? 255:this.data.rgb.b+this.data.seize
})
}
changeR(){
this.setData({
// '对象.属性'字符串包裹 rgb只有255 大于255就等于255 小于就+5
'rgb.r':this.data.rgb.r+5>255?255:this.data.rgb.r+5
})
},
最牛逼的来了啊
// 监听对象和数据的新值和变化
observers:{
监听rgb对象的三个 分别逗号隔开 r,g,b 三个属性 获取所有的属性 对象.**通配符
'rgb.r,rgb.g,rgb.b'(r,g,b){
this.setData({
为fullColor 模板字符串 分别赋值于rgb.r.g.b三个属性
因为我view的background-color就是绑定的fullColor相当于的点击就改变其rgb的颜色
fullColor:`${r},${g},${b}`
})
}
}
// rgb.r,rgb.g,rgb.b 获取对象的属性 **直接遍历对象所有的属性
通配符遍历对象 获取所有的属性 复制到obj的对象里面 在obj里面就有了.r.g.b三个属性了
'rgb.**'(obj){
this.setData({
fullColor:`${obj.r},${obj.g},${obj.b}`
})
},
34.纯数据字段 :不用于界面渲染的data字段 提示性能
在某些data的字段 不会显示在界面上 也不会传递给其他的组件 只在当前组件的内部里面使用,而纯数据字段可以去提升页面更新的性能
使用规则:在Component构造器的options节点中 指定pureDataPattern为一个正则表达式 当字段名称符合这个正则的字段就是纯数据字段
options:{
pureDataPattern:/^_/
},
在data中定义
_变量名:0 ,//说明这个变量名只是用于计算 不用于渲染
35.组件的全部生命周期函数
created 无 在组件实例创建时执行
attached 在组件实例进入页面节点树时执行
ready 少 组件在视图层布局完成后执行
moved 少 在组件实例被移动到节点树另一个位置时执行
detached 多 在组件实例被从页面节点树移除时执行
error object Error 组件方法抛出错误时执行
主要的生命周期函数: 组件中的生命周期函数 !!!很重要啊
main:created attached detached
1.created:刚刚创建完成 此时不能调用setData 在给组件的this添加自定义属性字段
2.attached:完全初始化完成后 进入页面节点树 执行 this.data可以使用 例如一些请求获取初始数据在这定义 (发请求初始数据)
3.detached:退出一个页面可以触发页面内每个自定义组件的detached函数 清理性质的工作
当组件卸载完成之后不是所有变量被清空 需要在detached中清空
这种是旧方式 不推荐
created(){
console.log("created");
},
attached(){
console.log("attached");
},
新方式 在lifetimes中定义 生命周期
lifetimes:{
created(){
console.log("created");
},
attached(){
console.log("attached");
},
}
36.自定义组件的行为依赖于页面状态的变化 组件的生命周期
show 组件页面被展示执行
hide 组件页面被隐藏执行
resize 组件页面尺寸变化执行
pageLifetimes节点中执行
// 随机颜色 给r,g,b向下取整 于随机数 在256的区间范围
_randomColor(){
this.setData({
_rgb:{
r:Math.floor(Math.random()*256),
g:Math.floor(Math.random()*256),
b:Math.floor(Math.random()*256),
}
})
}
在页面的生命周期的展示之后 去调用随机函数
37.插槽 提供一个<slot>节点插槽 承载组件使用者提供的我想买了解构
启用多个插槽在组件的js文件中声明 options节点
options:{
multipleSlots:true
}
1.
<!-- 给子组件传值 -->
<my-test1 max='10'>
<!-- 插槽 -->
<view> 这是通过插槽填充的内容</view>
<!-- 具名插槽的使用 -->
<view slot='before'>
我草拟吗
</view>
</my-test1>
2.
在组件中 插槽占位
<!-- 这里插槽占位 -->
<slot></slot>
<!-- 具名插槽 -->
<slot name='before'></slot>
在wxml文件定义 两个插槽 具名插槽 定义了name属性为before和after
test4文件中定义:
<slot name='before'>插槽的内容</slot>
<view>
组件的内部解构
</view>
<slot name="after">插槽的内容</slot>
在contact页面中使用了全局注册组件my-test4中 为view盒子定义slot='test4文件定义的名字>
<my-test4>
<view slot='before'> 这是通过插槽填充的内容</view>
<view slot='after'> 这是通过插槽填充的内容</view>
</my-test4>
!!!!!!!!!!!!!!!!
38.父子组件的通信
第一种:属性绑定 :父组件向子组件指定属性设置数据 设置json兼容的数据
第二种:事件绑定 :子传父 传递任意数据
第三种:获取组件实例:父组件通过this.selectComponent()获取子组件的实例对象
直接访问子组件的任意数据和方法
属性绑定:父组件向子组件 count是父 test5是子
父组件 定义 count
在contact父组件文件使用<my-test5 count="{{count}}"></my-test5>
<view>
父组件中的count值是{{count}}
</view>
在test5的js下定义组件的属性列表
properties:{
count: //定义 传递过来的参数是number类型
},
在test5下 定义接受过来的参数
addCount(){
this.setData({
// 这里是加接受过来的count数字类型
count:this.properties.count+1
})
}
!!!
第三种:事件绑定 子项父组件传值 子传父 传递任意数据
相当于儿子不能主动给父亲的数据,子传父实际上是父亲给儿子一个事件调用 让儿子吧数据放在参数中带回来给父亲
1.父组件的js中 定义一个函数 通过自定义事件的形式 传递给子组件
contact父组件js 定义函数
syncCount(e){
// console.log("syncCount");
// console.log(e.detail.value);
// 我这里可以接收到test5传递的新值
this.setData({
count:e.detail.value
})
},
2.父组件的wxml中 通过自定义事件的形式,将第一步定义的函数引用,传递给子组件
<!-- 这里绑定 syncCount()的函数 传递给子组件 -->
<my-test5 count='{{count}}' bind:sync='syncCount'></my-test5>
3.在子组件的js中 通过调用this.triggerEvent('自定义事件名称',{/*参数对象*/}) 数据发送到父组件
addCount(){
this.setData({
// 这里是加接受过来的count数字类型
count:this.properties.count+1
})
// 触发自定义事件 将数值同步给父组件
this.triggerEvent("sync",{value:this.properties.count})
}
4.父组件的js中 通过e.detail获取到子组件传递过来的数据
contact父组件 定义函数
syncCount(e){
// console.log("syncCount");
// console.log(e.detail.value);
// 我这里可以接收到test5传递的新值
this.setData({
count:e.detail.value
})
},
5.组件上定义一个自定义事件 事件的回调函数在父组件上定义 将自定义事件传递给子组件,由子组件触发的时候传参
<button bindtap="addCount">+1</button>
第三种 获取组件实例 在父组件中直接获取子组件的实例 获取子组件的函数和变量 很方便吧
在父组件调用 this.selectComponent("id&&class")选择器 获取子组件的实例对象 ,直接访问子组件的任意数据和方法 调用时传入一个选择器
this.selectComponent(".my-component")
<!-- 这里绑定 syncCount()的函数 传递给子组件 -->
<my-test5 count='{{count}}' bind:sync='syncCount' class="customA" id="ca"></my-test5>
<!-- 按钮绑定一个getChild方法 -->
<button bindtap="getChild">获取子组件实例</button>
// 按钮的tap事件处理函数
getChild(){
// 参数里面不能传递标签选择器 会返回null 类和id可以传
const child=this.selectComponent('.customA')
child.setData({
count:child.properties.count+1
})
child.addCount(); //调用子组件的addCount方法
}
!!!!!
39.自定义组件 behaviors 实现组件之间代码共享的特性 vue.js的mixins
behaviors可以写生命周期
创建一个behavior文件夹 存放一个js文件
创建一个共享的behavior实例对象 让所有的组件使用
// 向外导出 data properties methods
module.exports=Behavior({
// 私有数据节点
data:{
username:'aijing'
},
// 属性节点
properties:{
},
// 事件处理函数和自定义方法节点
methods:{
}
})
导入并且使用behavior
在组件中,使用require()方法导入需要的behavior,挂在后即可访问behavior中的数据和方法
// 导入require
const myBehavior=require("../../behaviors/my-behaviors")
Component({
behaviors:[myBehavior],
再导入这个组件 直接使用data
<view>
在behavior中定义的用户名:{{username}}
</view>
5.behavior中所有可用的节点
properties 同组件的属性
data: 同组件的数据
methods:同自定义组件的方法
behaviors:引入其他的behavior 引入其他的behavior
!!小程序对npm的支持和限制
不支持node.js的包,浏览器内置对象的包 c++ 包
vant weapp是微信小程序 vant是移动端的 elementUI是桌面端使用
在小程序中导入vant
在文件夹右键 打开cmd npm init -y 重启
导入vant的npm i @vant/weapp@1.3.3 -S --production
在工具 下 构建npm包 重启
全局导入和按需导入
在app.js 按钮导入
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
css变量定制vant主题样式:
在app.wxss中定义全局的css变量
page{
}
css的变量 可控 提高维护性 变量名以--开头
1.声明变量
--变量名:;
2.使用: background-color:var(--变量名)
比如说 我定义一个.box盒子 那就可以在两个盒子里面使用
.box,.box2{
--main:;
}
那我只能在box下面使用这个变量 外部访问不到这个变量
在小程序中 可以在app.wxss中配置全局变量
npm i --save miniprogram-api-promise@1.0.4
每次安装完一个包 都要构建一次npm
!!!!!
39.promise 的异步api 这样请求会更good
API的Promise化:通过额外的配置 将基于回调函数的API 升级为基于Promise的异步API 避免回调地狱的问题 依赖于一个包
miniprogram-api-promise
先安装
npm install --save miniprogram-api-promise@1.0.4
https://applet-base-api-t.itheima.net/api/get
// app.js写
// 在小程序的入口文件app.js中 只需调用一次promisifyAll()方法
// 实现异步API的Promise化
import {promisifyAll} from 'miniprogram-api-promise'
const wxp=wx.p={}
promisifyAll(wx,wxp)
之后通过wx.p()方法调用promise化之后的api
到index.js中 异步请求 async和await方法
async getInfo() {
const {
data: res
} = await wx.p.request({
method: "GET",
url: "https://autumnfish.cn/artist/top/song?id=6452",
// data: {
// name: 'aijing',
// age: 18
// }
})
console.log(res);
},
40.全局数据共享 :状态管理 解决组件之间数据共享的问题 Vuex Redux MobX
mobx-miniprogram配合mobx-miniprogram-bindings实现全局数据共享
mobx-miniprogram:创建Strore实例对象
mobx-miniprogram-bindings:吧Store中的共享数据或方法 来绑定到组件或页面里面使用
在小程序中安装MobX的包 两个包
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
1.创建一个store文件夹 下面一个js文件
// 在这个js文件 创建Store的实例对象
import {observable,action} from 'mobx-miniprogram'
// 按需导出 store对象
export const store=observable({
//字段和属性
numA:1,
numB:2,
// 计算属性 get只读不能修改
get sum(){
return this.numA+this.numB
},
// actions函数 专门修改store中数据的值 要先导入action才可以使用
updateNum1:action(function(step){
this.numA+=step
}),
updateNum2:action(function(step){
this.numB+=step
})
});
2.到需要使用的文件 先导入其createStoreBindings和store里面定义的字段和属性 与方法
// 导入Store中的共享数据或方法 来绑定到组件或页面里面使用
import {createStoreBindings} from "mobx-miniprogram-bindings"
import {store} from "../../store/store"
在网页加载的时候 通过this.storeBindings=createStoreBindings方法(this,为当前页面,和配置对象 store fieldss是字段和属性 actions是方法
获取到store里面的方法和属性与字段
onLoad(options) {
// 第二个this是指定到当前的页面
this.storeBindings=createStoreBindings(this,{
store,
fields:['numA','numB','sum'],//字段和属性在fields领域里面
actions:["updateNum1",]//方法
})
},
3.到wxhml里面 绑定data-step="{{1}}”这里是给store获取的updateNum1(step)形参传参
<view>
{{numA}}+{{numB}}={{sum}}
</view>
<!-- 这里是data-step是传递值 -->
<van-button type='primary' bindtap="btnHandler1" data-step="{{1}}">
numA+1
</van-button>
<van-button type='danger' bindtap="btnHandler1" data-step="{{-1}}">
numA-1
</van-button>
bindtap="btnHandler1" 为绑定 获取的updateNum(传参 e.target.dataset.step)页面的传参放在这里 传递给store里面的函数进行处理
// 两个按钮
btnHandler1(e){
console.log(e);
this.updateNum1(e.target.dataset.step)
},
!!
在组件中使用store
// components/numbers/numbers.js
// 导入store
import {storeBindingsBehavior} from "mobx-miniprogram-bindings"
import {store} from '../../store/store'
Component({
behaviors:[storeBindingsBehavior],
storeBindings:{
// 数据源
store,
fields:{
numA:'numA',
numB:'numB',
sum:"sum"
},
actions:{
updateNum2:"updateNum2"
}
},
!!!分包:
上线的时候 按用户的需求下载不同的包
主包:默认下载主包内的页面:tabbar页面放在主包里面
当用户进入分包内某个页面时,客户端将对应分包下载,
非tabbar页面按功能不同划分为不同的分包进行按需加载
所有分包不能超过16m
单个分包和主包不能超过2m
分包的配置:在app.json中配置 subpackages
"subPackages": [
{
"root": "pkgA",
"pages":[
"pages/cat/cat",
"pages/dog/dog"
]
},{
"root": "pkgB",
"pages":[
"pages/apple/apple"
]
}
],
主包无法访问分包的私有资源
分包之间也不能互相访问资源
分包可以访问主包的资源
!
独立分包:
独立分包与普通分包的区别:
普通的分包必须依赖主包来运行,独立分包可以在不下载主包的情况独立运行
"independent": true 来控制是不是独立分包
"subPackages": [
{
"root": "pkgA",
"pages":[
"pages/cat/cat",
"pages/dog/dog"
]
},{
"root": "pkgB",
"pages":[
"pages/apple/apple"
],
"independent": true
}
],
!!
分包的预下载: 在进入指定的页面时触发 在app.json中 使用preloadRule节点定义分包的预下载规则
"preloadRule": {
"pages/user/user":{
"packages": ["p1"] 进入user的tabbar页面会预下载一个叫p1的分包
}
},
"subPackages": [
{
"root": "pkgA",
"name": "p1", //这里要给分包pkgA命名为 p1 就会找到这个
"pages":[
"pages/cat/cat",
"pages/dog/dog"
]
自定义tabbar
在tabbar节点中不要删除list数组 因为保持低版本的兼容
添加 custom:true 顾客为true
添加tabBar代码文件
根目录下添加入口文件 新建一个 custom-tab-bar的文件夹
里面新建 component文件为 index文件 会在底部显示
绑定事件 是这个 bind:change="onChange"
<van-tabbar active="{{ active }}" bind:change="onChange">
<van-tabbar-item icon="home-o">标签</van-tabbar-item>
<van-tabbar-item icon="search">标签</van-tabbar-item>
<van-tabbar-item icon="friends-o">标签</van-tabbar-item>
<van-tabbar-item icon="setting-o">标签</van-tabbar-item>
</van-tabbar>
data:{active:0}//默认第一项被选中
// event.detail 的值为当前选中项的索引
onChange(event) {
console.log(event.detail);
this.setData({
active:event.detail
})
}
其自定义图标在vant组件库 定义了插槽 通过image来绑定 slot
<image slot='icon'>//默认
<image slot='icon-active'>//点击选中的图标样式
!!!!!!!!!!
最牛逼的来了,可以将app.json中的tabbar栏的配置复制到index.js中的data 通过循环遍历 这个配置完成的
这里来自定义tabbar底部栏
安装vant-weap
会modox 的store 小程序的状态管理工具
将app.json的tabbar里面配置 custom:true 开启自定义tab栏
创建一个文件夹 必写 custom-tab-bar 在里面创建index的component组件
在index.wxml中
这是vant的tabbar标签栏的
<van-tabbar active="{{active}}"
bind:change="onChange" active-color='pink'>
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info?item.info:''}}">
<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>
在小程序中安装MobX的包 两个包
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
创建一个store文件夹 的sotre.js
//在这个js文件中 创建store的实例对象
// 导入这个包的成员
import {
observable,action
} from 'mobx-miniprogram'
// 得到这个实例对象 导出
export const store = observable({
numA: 10,
numB: 20,
userPerson:{
name:'aijing',
age:18,
sex:"男"
},
// 选中项的索引值
activeTabBarIndex:0,
// 计算属性 get 代表这个方法只读
get sum() {
return this.numA + this.numB
},
// action 修改值
updateNum1:action(function(step){
this.numA+=step
}),
updateNum2:action(function(step){
this.numB+=step
}),
// 修改userPerson.name 传递的str等于这个
updateName:action(function(str){
this.userPerson.name+=str
console.log(this.userPerson.name,"我是顶真",str);
}),
// 传递一个新值 给当前的
updateActiveTabBarIndex:action(function(index){
this.activeTabBarIndex=index
})
})
在组件中使用store 使用store要导包
// custom-tab-bar/index.js
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
import {store} from '../store/store'
Component({
开启样式互通
options:{
styleIsolation:"shared"
},
behaviors:[storeBindingsBehavior],
storeBindings:{
store,
fields:{
sum:"sum",
active:"activeTabBarIndex"
},
actions:{
updateActive:"updateActiveTabBarIndex"
}
},
observers:{
"sum":function(val){
console.log(val);
// 让data的list数组第一个的info赋值val最新值
this.setData({
"list[1].info":val
})
}
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
list: [{
"pagePath": "/pages/index/index",
"text": "首页",
"iconPath": "/assets/21.webp",
"selectedIconPath": "/assets/23.webp",
info:0
},
{
"pagePath": "/pages/money/money",
"text": "秦蓉",
"iconPath": "/assets/24.webp",
"selectedIconPath": "/assets/25.webp",
info:2
},
{
"pagePath": "/pages/message/message",
"text": "消息",
"iconPath": "/assets/28.webp",
"selectedIconPath": "/assets/29.webp"
}
]
},
/**
* 组件的方法列表
*/
methods: {
// event.detail 的值为当前选中项的索引
onChange(event) {
// console.log(event.detail);
this.setData({
active: event.detail
})
// 调用store的方法 传递一个索引
this.updateActive(event.detail)
// 跳转到tabbar的页面
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
}
}
})