Skip to content

全局生命周期函数

属性类型必填说明
onLaunchfunction监听小程序初始化,全局只会执行 1 次
onShowfunction监听小程序启动或切前台。
onHidefunction监听小程序切后台。

局部生命周期函数

属性类型说明
onLoadfunction页面加载时触发 (一个页面只会调用一次)
onShowfunction页面显示时触发,页面显示/切入前台时触发
onReadyfunction页面初次渲染完成时触发(一个页面只会调用一次
onHidefunction页面隐藏/切入后台时触发
onUnloadfunction页面卸载时触发

组件生命周期函数

js
Component({
  
   #组件的生命周期
  lifetimes: {
    created: function () {
      // 在组件实例刚刚被创建时执行,注意此时不能调用 setData 
      // 一般用来为组件添加一些自定义属性字段。
    this.test = '测试'
    },
    attached: function() {
      // attached 在组件完全初始化完毕、进入页面节点树后执行
      // 模板已经解析完毕,并且挂载到页面上
      // 一般都是在这里写对应的交互
        console.log(this.test)
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    },
  },
    
  # 组件所在页面的生命周期
  pageLifetimes: {
    // 监听组件所在的页面展示(后台切前台)状态
    show () {
      console.log('组件所在的页面被展示')
    },
    // 监听组件所在的页面隐藏(前台切后台、点击 tabBar)状态
    hide () {
      console.log('组件所在的页面被隐藏')
    }

  }

})

微信小程序四个文件

  • js:页面逻辑-必须存在
  • wxml:页面结构-必须存在
  • json:小页面配置
  • wxss:页面样式

遍历、判断、显示隐藏

vue
  <!-- 小程序遍历内置item和index -->
  <!-- 遍历对象时需要绑定wx:key  wx:for-item="students" wx:for-index="key"  这两个是重新指定每一项和下标的名称-->
  <view wx:key="id" wx:for="{{students}}" wx:for-item="students" wx:for-index="key" class="table">
    <!-- wx:if="{{students.age > 18}}" 暂时移除条件-->
    <text>{{key+1}}</text>
    <text>{{students.name}}</text>
    <text>{{students.age}}</text>
    <text>{{students.gender}}</text>
  </view>
  <!-- 遍历数组或者字符串时绑定的wx:key="*this" -->
  <text wx:for="{{bro}}" wx:key="*this">{{item}}</text>

  <!-- 测试if elif else -->
  <view>
    <text wx:if="{{num === 1}}">您现在是{{num}}级别111</text>
    <text wx:elif="{{num === 2}}">您现在是{{num}}级别222</text>
    <text wx:else>您现在是{{num}}级别🐂</text>
  </view>

  <!-- 测试wx:if 与 hidden -->
  <button type="primary" bind:tap='toggle'>显示/隐藏</button>
  <!-- wx:if与v-if类似,是惰性的,如果首次不加载的话可以节省资源 -->
  <view wx:if="{{hidden}}">{{msg}}</view>
  <!-- 变量hidde值是true,这边要取反,不然就隐藏了  hidden与v-show类似 -->
  <view hidden="{{!hidden}}">{{msg}}</view>



url="{{'/pages/notify/index?id='+item.id}}"  带参跳转

scroll-view使用

html
<scroll-view
  class="scroll-y"
  scroll-y //开启y轴滚动
  lower-threshold="100" //距离底部还剩余多少触发下拉加载
  bindscrolltolower="getMore" //下拉加载事件
  enable-back-to-top //点击顶部栏返回顶部
             
  refresher-enabled  //开启下拉刷新
  refresher-default-style="black" // loading效果
  refresher-background="#f7f7f8" // loading背景颜色
  bindrefresherrefresh="onrefresh" //上拉刷新函数
  refresher-triggered="{{ triggered }}"  //loading的显示状态
>

  <view wx:for="{{ arr }}" wx:key="*this">{{ item }}</view>

</scroll-view>

微信小程序发布上线流程

开发者身份 ==> 分包 ==> 上传填写版本号 ==> 审核 ==> 上传发布

微信小程序最大宽是750rpx

微信小程序自定义导航栏

在app.json(全局)或者 page内的.json文件内配置navigationStyle

js
{
  "usingComponents": {},
  "navigationStyle": "custom"
}

微信小程序的两种渲染模式

Skyline,在低版本的客户端中,将使用 WebView 渲染模式进行渲染。在全局app.json中配置渲染模式

image-20240409184350263

小程序事件处理

  • 获取值:event.detail.value
  • 阻止冒泡:将bindtap变成catchtap
  • 事件传参:在标签上用data-id="1"
  • 获取用event.currentTarget.dataset(事件绑定者身上的数据,冒泡) event.target.dataset(触发者本身上的数据)
  • 事件传参:mark:id="1" 获取用event.mark 父元素绑定mark时也能通过冒泡机制访问到

小程序数据双向绑定:model:value=""

block:不是页面组件,仅用于包裹元素,支持列表渲染、条件渲染等,类似vue中template

小程序跳转方式

  • wx.switchTab:只能跳转tabBar页面,路径后不能带参数
  • wx.navigateTo:保留当前页面,跳转下一页面,不能跳转到tabBar
  • wx.redirectTo:关闭当前页面,跳转下一页面,不能跳转到tabBar
  • wx.reLaunch:关闭所有页面打开指定页面( 页面栈也清空了 )

路由传参--通过onLoad生命周期获取

js
wx.navigateTo({
      url: '/pages/list/list?id=1&name=tom'
    })

#获取参数
onLoad(options){
    console.log(options)
}

小程序组件---父传子

组件设置样式必须优先用class,color/font会从组件外继承

开发中常见的组件主要分为 公共组件 和 页面组件 两种,因此注册组件的方式也分为两种:

  1. 全局注册:在 app.json 文件中配置 usingComponents 节点进行引用声明,注册后可在任意组件使用
  2. 局部注册:在页面的 json 文件中配置 usingComponents 节点进行引用声明,只可在当前页面使用
js
{
  "usingComponents": {
    "自定义组件的标签名": "自定义组件文件路径"
  }
}

组件中的方法必须写在methods中--含父传子

js
#使用组件并传参的方式
<custom-checkbox label="我已阅读并同意 用户协议 和 隐私协议" position="right" />
    
#custom-checkbox组件
//wxml中的代码
<view class="custom-checkbox-container">
  <view class="custom-checkbox-box {{ position === 'right' ? 'right' : 'left' }}">
    <checkbox class="custom-checkbox" checked="{{ isChecked }}" bindtap="updateChecked" />
    <view>
      <text>{{ label }}</text>
    </view>
  </view>
</view>

//js中的代码
Component({ //注意此处是Component
  options: { //样式隔离选项 默认`isolated`,apply-shared:父影响子,但子不影响父; shared:影响全局及其他为shared的组件
    styleIsolation: 'apply-shared'
  },
    
   // 组件的属性列表,主要用来接收组件使用者传递给组件内部的属性以及数据
   properties: {
    // 如果需要接收传递的属性,有两种方式:全写、简写
     // label: String
    label: {
     // 数据类型:String、Number、Boolean、Object、Array 也可以设置为 null,表示不限制类型
       type: String,
       value: ''
     },
     // 文字显示位置
     position: {
       type: String,
       value: 'right'
     }
   },
    
  data: {
    isChecked: false
  },
    
  methods: {
    // 更新复选框的状态
    updateChecked () {
      this.setData({
        isChecked: !this.data.isChecked
      })
      console.log(this.properties.label) //可以拿到传进来的数据 也可以通过setData修改 但是不建议
        //要是修改建议用 下方的监听器  监听传进来的数据然后进行修改
    }
  }
})

子传父通信--通过triggerEvent('事件名',数据)

js
#子组件中
<button type="primary" plain bindtap="sendData">传递数据</button>
#.js
Component({
  // 组件的初始数据
  data: {
    num: 666
  },
  methods: {
    // 将数据传递给父组件
    sendData () {
      // 需要使用 triggerEvent 发射自定义事件, 第二个参数,是携带的参数
      this.triggerEvent('myevent', this.data.num)
    }
  }
})

#.wxml父组件
<view>{{ num }}</view>
<!-- 需要在自定义组件标签上通过 bind 方法绑定自定义事件,同时绑定事件处理函数 -->
<custom05 bind:myevent="getData" />
#.js
Page({
  data: {
    num: ''
  },
  getData (event) {
    // 可以通过事件对象event.detail 获取子组件传递给父组件的数据
    this.setData({
      num: event.detail
    })
  }
})

获取子组件实例selectComponent()方法

js
<!-- 父组件 -->
<costom bind:myevent="getData" class="custom" />
<button bindtap="getChildComponent"></button>

// 父组件
Page({
  data: {},
  getChildComponent: function () {
    const child = this.selectComponent('.custom') //填写id或者类
    console.log(child)
  }
})

数据监听器-只能在组件中使用

可以用于监听和响应任何属性和数据字段的变化,有时,需要在一些数据字段被 setData 设置时,需要执行一些操作。那么就可以使用 observers 数据监听器来实现。语法如下:

js
Component({
  data: {
    num: 10,
    count: 1,
    obj: { name: 'Tom', age: 10 },
    arr: [1, 2, 3]
  },
  observers: {
    // key 是需要检测数据
    // value 是一个函数,函数接收一个形参作为参数,是最新的值
    num: function(newNum) {
      console.log(newNum)
    },
    
    // 数据监听器支持监听属性或内部数据的变化,可以同时监听多个
    'num, count': function (newNum, newCount) {
       console.log(newNum, newCount)
    }
    
    // 监听器可以监听子数据字段
    'obj.age': function(newAge) {
      console.log(newAge)
    },
    
    // 如果需要监听所有子数据字段的变化,可以使用通配符 ** 
    'obj.**': function(newAge) {
      console.log(newAge)
    },
        
    'arr[0]': function (val) {}
  }
})

使用 Component 构造页面

  • 📌 注意事项:

    1. 要求对应 json 文件中包含 usingComponents 定义段

    2. 页面使用 Component 构造器创建,需要定义与普通组件一样的字段与实例方法

    3. 页面 Page 中的一些生命周期方法(如 onLoad() 等以“on”开头的方法),在 Component 中要写在 methods 属性中才能生效

    4. 组件的属性 Properties 可以用于接收页面的参数,在 onLoad() 中可以通过 this.data 拿到对应的页面参数

js
Component({

  # Component 方法功能比 Page 方法强大很多
  # 如果使用 Component 方法构造页面,可以实现更加复杂的页面逻辑开发,可以使用监听器

  // 注意事项:
  // 1. 要求 .json 文件中必须包含 usingComponents 字段
  // 2. 里面的配置项需要和 Component 中的配置项保持一致
  // 3. 页面中 Page 方法有一些钩子函数、事件监听方法,这些钩子函数、事件监听方法必须方法 methods 对象中
  // 4. 组件的属性 properties 也可以接受页面的参数,在 onLoad 钩子函数中可以通过 this.data 进行获取

  properties: {
    id: String,
    title: String
  },
  data: {
    name: 'tom'
  },

  methods: {
    // 更新 name
    updateName() {
      this.setData({
        name: 'jerry'
      })
    },
    onLoad (options) {
      console.log(this.data.id)
      console.log(this.data.title)
      console.log(this.properties.id)
    },
  }
})

插槽

js
#custom01.wxml
<view>
  <slot name="slot-top" /> //具名
  <view><slot /></view> // 默认
  <slot name="slot-bottom" /> //具名
</view>

#custom01.js
Component({
  options: {
    multipleSlots: true //开启多插槽的支持
  }
})


#.json文件中注册
{
  "usingComponents": {
    "自定义组件的标签名": "自定义组件文件路径"
  }
}
#使用
<custom01>
  <text slot="slot-top">我需要显示到顶部</text>
  我是子节点内容  //显示到默认的位置
  <text slot="slot-bottom">我需要显示到低部</text>
</custom01>

通过npm安装第三方vant组件库

js
#项目根目录 
npm init -y
npm i @vant/weapp -S --production
#在app.json中去除styleV2
#构建--如果要自定义构建,这边就先别构建
工具---构建npm

自定义npm构建

将所有代码都移入新建的miniprogram中,并且在project.config.json中的setting配置项内进行配置

image-20240415184800434

微信小程序分包

  • app.json中,通过subPackages字段声明分包结构
  • 一个分包配置一个对象,分包+主包规定目前不能超过20MB
  • 主包不能引用分包资源,分包可以引用主包资源,分包与分包资源不能相互引用
  1. root 字段指定了分包的根目录,该目录下的所有文件都会被打包成一个独立的包
  2. name 字段为分包的名称,用于在代码中引用该分包
  3. pages 字段指定了该分包中包含的页面,可以使用通配符 * 匹配多个页面
image-20240415233146708
js
#跳转方式  / + 分包路径 + 页面地址
<navigator url="/modules/goods/pages/list/list">toListPage</navigator>

分包预下载(含独立分包配置)

需要在 app.json 中通过 preloadRule 字段设置预下载规则。

json
{
    #分包
  "subPackages": [
    {
      "root": "modules/goods", #分包根路径
      "name": "goods",#分包别名
      "pages": [
        "pages/list/list",#分包页面
        "pages/detail/detail"
      ]
    },
    {
      "root": "modules/marketModule",
      "name": "marketModule",
      "pages": [
        "pages/market/market"
      ],
      "independent": true #开启独立分包
    }
  ],
    
  "preloadRule": {
    "pages/index/index": { #访问此页面会预下载下方配置的页面
      "network": "all", #网络条件
      "packages": ["modules/goodModule"] #可配置分包根路径(root)或者是name
    },
    "modules/marketModule/pages/market/market": { #访问独立分包下载主包
      "network": "all",
      "packages": ["__APP__"] #主包特有的写法
    }
  }
}

框架接口-getApp 全局共享数据

➡️ app.js

js
App({
  // 全局共享的数据
  globalData: {
    token: ''
  },
  // 全局共享的方法
  setToken (token) {
    // 如果想获取 token,可以使用 this 的方式进行获取
    this.globalData.token = token
    // 在 App() 方法中如果想获取 App() 实例,可以通过 this 的方式进行获取
  }
})

➡️ pages/index/index.js

js
// getApp() 方法用来获取全局唯一的 App() 实例
const appInstance = getApp()
Page({
  login () {
    console.log(appInstance)
    appInstance.setToken('fghioiuytfghjkoiuytghjoiug')
  }
})

微信小程序事件总线pubSub

用于组件之间的相互通信

js
# npm install pubsub-js  
# 构建npm
#发布事件的组件
import pubSub from 'pubsub-js'
Component({
	properties: {},
	data: {
		name:'tom'
	},
	methods: {
		sendData(){
			//发布事件
			pubSub.publish('pubSendData',{name:this.data.name,age:18})
		}
	}
})

#接收事件的组件
import pubSub from 'pubsub-js'
Component({
	properties: {},
	data: {
		name:''
	},
	methods: {},
	lifetimes:{
		attached(){
			pubSub.subscribe('pubSendData',(msg,data)=>{
				console.log(msg,data);//pubSendData {name: "tom", age: 18}
				this.setData({
					name:data.name
				})
			})
		}
	}
})

uniapp也可以用vue的生命周期,在是组件的情况下推荐用vue的,在是页面的情况下推荐用uniapp的

小程序适配刘海屏

import { xxx } from '@dcloudio/uni-app' //uniapp的生命周期引入方式

方法1

css
@media screen and (min-height: 812px) and (min-width: 375px) {
  /* 在iPhone X及以上设备上应用样式 */
  .header {
    padding-top: constant(safe-area-inset-top); /* 适配刘海屏的安全区域 */
  }
}

方法2:通过 uni.getSystemInfoSync()来解构出safeAreaInsets安全区域,这个解构出来的对象内有上下左右四个边距值,通过动态绑定style样式的paddingTop来解决刘海屏问题

image-20230901005407128

使用scroll-view必须要计算出滚动的可用高度

image-20230912224826909

处理图片加载失败的解决方法

image-20230912235907322