微信小程序大牛制作

选中一段文字  或 什么东西   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,
      })
    }
  }
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fameless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值