小程序50-75

一、小程序API

1.界面交互

(1)loading提示框

其中mask:布尔值

true表示用户在数据加载中不可以点击

false表示用户在数据加载中可以点击

javascript 复制代码
Page({


  data: {
    list: []
  },

  // 获取数据
  getData () {

    // 显示 loading 提示框
    wx.showLoading({
      // 用来显示提示的内容
      // 提示的内容不会自动换行,如果提示的内容比较多,因为在同一行显示
      // 多出来的内容就会被隐藏
      title: '数据加载中...',
      // 是否显示透明蒙层,防止触摸穿透
      mask:false
    })

    // 如果需要发起网络请求,需要使用 wx.request API
    wx.request({
      // 接口地址
      url: 'https://gamll-prod.atguigu.cn/mall-api/index/findBanner',
      // 请求方式
      method: 'GET',
      // 请求参数
      data: {},
      // 请求头
      header: {},
      // API 调用成功以后,执行的回调
      success: (res) => {
        // console.log(res)
        if (res.data.code === 200) {
          this.setData({
            list: res.data.data
          })
        }
      },
      // API 调用失败以后,执行的回调
      fail: (err) => {
        console.log(err)
      },
      // API 不管调用成功还是失败后,执行的回调
      complete: (res) => {
        // console.log(res)
        // 关掉 loading 提示框
        // hidLoading 和 showLoading 必须结合,配对使用才可以
        wx.hideLoading()
      }
    })

  }

})

(2)模态对话框-消息提示框

javascript 复制代码
// 写在page里面

  // 删除商品
  async delHandler() {

    // showModal 显示模态对话框
    const { confirm } = await wx.showModal({
      title: '提示',
      content: '是否删除该商品?'
    })

    if (confirm) {
      // showToast 消息提示框
      wx.showToast({
        title: '删除成功',
        icon: 'none',
        duration: 2000
      })
    } else {
      wx.showToast({
        title:'取消删除',
        icon: 'error',
        duration: 2000
      })
    }

2.本地存储

html 复制代码
<button size="mini" plain type="warn" bind:tap="setStorage">存储</button>
<button size="mini" plain type="primary" bind:tap="getStorage">获取</button>
<button size="mini" plain type="warn" bind:tap="removeStorage">删除</button>
<button size="mini" plain type="primary" bind:tap="clearStorage">清空</button>
javascript 复制代码
// pages/cate/cate.js
Page({


  // 将数据存储到本地
  setStorage () {

    // 第一个参数:本地存储中指定的 key
    // 第二各参数:需要存储的数据
    wx.setStorageSync('num', 1)

    // 在小程序中
    // 如果存储的是对象类型数据,不需要使用JSON.stringify 和 JSON.parse 进行转换
    // 直接进行存储和获取即可
    wx.setStorageSync('obj', {name: 'tom', age: 10 })

    // ----------------- 异步 API ---------------------------
    wx.setStorage({
      key: 'num',
      data: 1
    })

    wx.setStorage({
      key: 'obj',
      data: { name: 'jerry', age: 18 }
    })

  },

  // 获取本地存储的数据
  async getStorage () {

    // 从本地存储的数据中获取指定 key 的数据 内容
     const num = wx.getStorageSync('num')
     const obj = wx.getStorageSync('obj')

     console.log(num)
     console.log(obj)

    // ----------------- 异步 API ---------------------------

     const {data} = await wx.getStorage({
      key: 'obj'
    })

    console.log(data)
  },

  // 删除本地存储的数据
  removeStorage () {

    // 从本地移除指定 key 的数据 内容
    wx.removeStorageSync('num')

    // ----------------- 异步 API ---------------------------

    wx.removeStorage({
      key: 'num'
    })
  },

  // 清空本地存储的全部数据
  clearStorage () {
    
    // 不需要存任何参数
    wx.clearStorageSync()

    // ----------------- 异步 API ---------------------------

    wx.clearStorage()
  },


})// pages/cate/cate.js
Page({


  // 将数据存储到本地
  setStorage () {

    // 第一个参数:本地存储中指定的 key
    // 第二各参数:需要存储的数据
    wx.setStorageSync('num', 1)

    // 在小程序中
    // 如果存储的是对象类型数据,不需要使用JSON.stringify 和 JSON.parse 进行转换
    // 直接进行存储和获取即可
    wx.setStorageSync('obj', {name: 'tom', age: 10 })

  },

  // 获取本地存储的数据
  getStorage () {

    // 从本地存储的数据中获取指定 key 的数据 内容
    const num = wx.getStorageSync('num')
    const obj = wx.getStorageSync('obj')

    console.log(num)
    console.log(obj)

  },

  // 删除本地存储的数据
  removeStorage () {

    // 从本地移除指定 key 的数据 内容
    wx.removeStorageSync('num')

  },

  // 清空本地存储的全部数据
  clearStorage () {
    
    // 不需要存任何参数
    wx.clearStorageSync()

  },


})

3.路由与通信

(1)声明式导航:navigator 组件

(2)编程式导航:使用小程序提供的API

路径后可以带参数,参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔,eg:path?key=value&key2=value2

参数需要在跳转到的页面的onLoad钩子函数中通过形参进行接收

html 复制代码
<button plain type="warn">navigateTo</button>
<button plain type="primary">redireectTo</button>
<button plain type="warn">switchTab</button>
<button plain type="primary">reLaunch</button>



// list
<button plain type="warn">navigateBack</button>
javascript 复制代码
Page({

  navigateTo () {

    // 保留当前页面,跳转到应用中其他页面,不能跳转到 tabBar 页面
    wx.navigateTo({
      // 不知道为啥跳不过去,第一个跳转
      url: '/pages/list/list?id=1&name=tom'
      // url: '/pages/cate/cate'
    })

  },

  redireectTo () {

    // 关闭(销毁)当前页面,跳转到应用中其他页面,不能跳转到 tabBar 页面
    wx.redireectTo({
      url: '/pages/list/list?id=1&name=tom'
      // url: '/pages/cate/cate'
    })

  },

  switchTab () {

    // 跳转到 tabBar 页面,不能跳转道非 tabBar 页面,路径后面不能传递参数
    wx.switchTab({
      // url: '/pages/list/list'
      url: '/pages/cate/cate'
    })

  },

  reLaunch () {

    // 关闭所有的页面,然后跳转到应用中某一个页面
    wx.reLaunch({
      // url: '/pages/list/list'
      url: '/pages/cate/cate?id=1&name=tom'
    })

  },


})

// list

Page({

  navigateBack () {

    // 关闭当前页面,返回上一页或者返回多级页面
    // 默认返回上一页
    wx.navigateBack({
      delta: 1
    })

  },

  onLoad(options) {
    console.log(options)
  }

})

4.页面处理函数

(1)上拉加载

(2)下拉刷新

html 复制代码
<!--pages/market/market.wxml-->
<view wx:for="{{ numList }}" wx:key="this">{{ item }}</view>
javascript 复制代码
// market.json
{
  "usingComponents": {},
  "onReachBottomDistance": 100,
  "enablePullDownRefresh": true,
  "backgroundColor": "#efefef",
  "backgroundTextStyle": "light"
}
javascript 复制代码
// pages/market/market.js
Page({

  data: {
    numList: [1,2,3]
  },

  // 监听用户上拉加载
  onReachBottom () {
    // console.log('监听用户上拉加载')
    // 产品需求:
    // 当用户上拉,需要数字进行累加

    // 当用户上拉加载时,需要对数字进行累加,每次累加 3 个数字
    // 目前是 [1, 2, 3],[1, 2, 3, 4, 5, 6]
    // 怎么进行追加?
    // 获取目前数组最后一项 n, n + 1, n + 2, n + 3

    wx.showLoading({
      title: '数据加载中...',
    })

   setTimeout(() => {
     // 获取数组的最后一项
     const lastNum = this.data.numList[this.data.numList.length - 1]
     // 定义需要追加的元素
     const newArr = [lastNum + 1, lastNum + 2, lastNum + 3]
 
     this.setData({
       numList: [...this.data.numList, ...newArr]
     })

     wx.hideLoading()
   }, 1500)
  },

  // 监听用户下拉刷新
  onPullDownRefresh () {
    // console.log('监听用户下拉刷新')

    // 产品需求:
    // 当用户上拉加载更多以后,如果用户进行了下拉刷新
    // 需要将数据进行重置
    this.setData({
      numList: [1, 2, 3]
    })

    // 在下拉刷新之后, loading 效果有可能不会回弹回去
    if (this.data,numList.length === 3) {
      wx.stopPullDownRefresh()
    }
  }
})

5.拓展-增强 scroll-view

使用 scroll-view 实现上拉加载更多和下拉刷新功能

html 复制代码
<scroll-view 
  scroll-y 
  class="scroll-y"

  lower-threshold="100"  
  bindscrolltolower="getMore"
  enable-back-to-top

  refresher-enabled
  refresher-default-style="black"
  refresher-background="#f7f7f8"
  bindrefresherrefresh="refreshHandler"
  refresher-triggered="{{isTriggered}}"
>
  
  <view wx:for="{{ numList }}" wx:key="*this">{{ item }}</view>

</scroll-view>
css 复制代码
.scroll-y {
  height: 100vh;
  background-color: #efefef;
}

view {
  height: 400rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

view:nth-child(odd) {
  background-color: skyblue;
}

view:nth-child(even) {
  background-color: lightsalmon;
}
javascript 复制代码
// pages/profile/proflie.js
Page({

  data: {
    numList: [1, 2, 3],
    isTriggered: false
  },

  refreshHandler () {

    wx.showToast({
      title: '下拉刷新...'
    })

    this.setData({
      numList: [1, 2, 3],
      isTriggered: false
    })

  },

  // scroll-view 上拉加载更多事件的事件处理函数
  getMore () {
    wx.showLoading({
      title: '数据加载中...',
    })

   setTimeout(() => {
     // 获取数组的最后一项
     const lastNum = this.data.numList[this.data.numList.length - 1]
     // 定义需要追加的元素
     const newArr = [lastNum + 1, lastNum + 2, lastNum + 3]
 
     this.setData({
       numList: [...this.data.numList, ...newArr]
     })

     wx.hideLoading()
   }, 1500)

  }

})

二、自定义组件

1.创建和注册组件

2.组件的数据以及方法

html 复制代码
<!--index-->
<custom-checkbox />

<view class="line"></view>

<custom-checkbox />
html 复制代码
<!--components/custom-checkbox/custom-checkbox.wxml-->
<!-- <text>我是自定义属性</text> -->

<view class="custom-checkbox-container">
  <view class="custom-checkbox-box">
    <checkbox checked="{{ isChecked }}" bind:tap="updateChecked"/>
  </view>
</view>
javascript 复制代码
// components/custom-checkbox/custom-checkbox.js
Component({

  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据:用来定义当前组件内部所需要使用的数据
   */
  data: {
    isChecked: false
  },

  /**
   * 组件的方法列表:在组件中,所有的事件处理程序都需要写到 methods 方法中
   */
  methods: {
    
    // 更新复选框的状态
    updateChecked () {

      this.setData({
        isChecked: !this.data.isChecked
      })

    }

  }
})

3.组件的属性properties

html 复制代码
<!--index-->

<custom-checkbox label="我已阅读并同意 用户协议 和 隐私协议" position="right" />

<view class="line"></view>

<custom-checkbox label="匿名提交" position="left" />
html 复制代码
<!--components/custom-checkbox/custom-checkbox.wxml--><view class="custom-checkbox-container">
  <view class="custom-checkbox-box {{ position === 'left' ? 'left' : 'right' }}">
    <checkbox class="custom-checkbox" checked="{{ isChecked }}" bind:tap="updateChecked"/>

    <view>
      <text>{{ label }}</text>
    </view>
  </view>
</view>
css 复制代码
.custom-checkbox-box {
  display: flex;
  align-items: center;
}

.custom-checkbox-box.left {
  flex-direction: row-reverse;
}
.custom-checkbox-box.right {
  flex-direction: row;
}

.custom-checkbox {
  margin-left: 10rpx;
}
javascript 复制代码
/**
   * 组件的属性列表:组件的对外属性,主要用来接收组件使用者传递给组件内部的属性以及数据
   */
  properties: {
    // 如果需要接收传递的属性,有两种方式:全写、简写
    // label: String
    
    label: {
      // type 组件使用者传递的数据类型
      // 数据类型:String、Number、Boolean、Object、Array
      // 可以设置为 null,表示不限制类型
      type: String,
      value: ''
    },



/**
   * 组件的方法列表:在组件中,所有的事件处理程序都需要写到 methods 方法中
   */
  methods: {
    
    // 更新复选框的状态
    updateChecked () {

      this.setData({
        isChecked: !this.data.isChecked,
        label: '在组件内部也可以修改 properties 中的数据'
      })

      // 在JS中可以访问和获取 properties 中的数据
      // 但是一般情况下,不建议修改,因为会造成数据流的混乱
      // console.log(this.properties.label)

    }

  }

4.组件wxml的slot-插槽

html 复制代码
<!--cate-->
<custom01>
  <text slot="slot-top">我需要显示到顶部</text>
  <!-- 默认情况下,自定义组件的子节点内容不会进行展示 -->
  <!-- 如果想内容进行展示,需要在组件模板中定义 slot 节点 -->
  我是子节点内容
  <text slot="slot-bottom">我需要显示到底部</text>
</custom01>
html 复制代码
<!--index-->

<!-- label 文本显示的内容 -->
<!-- position 控制文本显示的位置 -->
<custom-checkbox label="我已阅读并同意 用户协议 和 隐私协议" position="right">
  我已阅读并同意 用户协议 和 隐私协议 - 111
</custom-checkbox>

<view class="line"></view>

<custom-checkbox label="匿名提交" position="left">
  匿名提交 - 222
</custom-checkbox>
html 复制代码
<!--components/custom-checkbox/custom-checkbox.wxml-->

<view class="custom-checkbox-container">
  <view class="custom-checkbox-box {{ position === 'left' ? 'left' : 'right' }}">
    <checkbox class="custom-checkbox" checked="{{ isChecked }}" bind:tap="updateChecked"/>

    <view>
    <!-- label 和 子节点内容都进行了展示 -->
    <!-- 要么展示 label 要么展示 子节点内容 -->
    <!-- 如果用户传递了 label 属性,就展示label -->
    <!-- 如果用户没有传递 label 属性,就展示子节点内容 -->
      <text wx:if="{{ label !== '' }}">{{ label }}</text>

      <slot wx:else />
    </view>
  </view>
</view>

5.组件样式以及注意事项

html 复制代码
<!--cate-->


<view class="custom parent">
  <view>
    <custom02 />

    <view class="son test">我是父级页面中的结构</view>
  </view>
</view>

<!-- <text>我是父级页面中的结构</text> -->
css 复制代码
/* cate */

/* .custom {
  color: lightseagreen;
  font-size: 50rpx;
} */

/* .label {
  color: lightseagreen;
} */

/* text {
  color: lightseagreen;
} */

.parent .son.test {
  color: lightsalmon;
}
html 复制代码
<!--components/custom02/custom02.wxml-->

<text class="content son">
  <text class="label">给自定义组件设置样式</text>
</text>
css 复制代码
/* components/custom02/custom02.wxss */

/* 第一个注意事项:在自定义的 wxss 文件中,不允许使用标签选择器,ID 选择器,属性选择器 */
/* 请改为class选择器 */
.content {
  color: lightgreen;
}

/* 第二个注意事项:子选择器,只能用于 view 和 子组件,用于其他组件可能会出现样式失效的问题 */
.content > .label {
  color: lightgreen;
}

/* 第三个注意事项:继承样式,例如:color/font 都会从组件外继承 */

/* 第四个注意事项:全局样式、组件所在页面的样式文件中的样式都对自定义组件无效 */

/* 第五个注意事项:官方不推荐做法 */
/* 不建议在全局样式文件以及父级页面之间使用标签选择器设置样式 */
/* 如果是在全局样式文件中设置样式,会影响项目中全部的相同组件 */
/* 如果是在页面样式文件中设置样式,会影响当前页面所有的相同组件 */

/* 第六个注意事项: */
/* 组件和组件使用者,如果使用了后代选择器,可能出现一些非预期情况 */
/* 如果出现,请避免 */

6.组件样式隔离

css 复制代码
/* components/custom03/custom03.wxss */

.test {
  color: lightseagreen;
  font-size: 50rpx;
}

// cate
.label {
  color: lightsalmon;
}
html 复制代码
<!--cate-->
<custom03 />

<view class="test">我是组件使用者中的结构</view>



<!--components/custom02/custom02.wxml-->

<text class="content son">
  <text class="label test">给自定义组件设置样式</text>
</text>
javascript 复制代码
// components/custom03/custom03.js
Component({

  options: {

    // styleIsolation:配置组件样式隔离

    // isolated:开启样式隔离,默认值
    // 在默认情况下,自定义组件和组件使用者如果存在相同的类名,类名不会互相影响

    // apply-shared:表示组件使用者、页面的 wxss 样式能够影响到自定义组件
    // 但是自定义组件的样式不会影响组件使用者、页面的 wxss 样式

    // shared:表示组件使用者、页面的 wxss 样式能够影响到自定义组件
    // 自定义组件的样式会影响组件使用者、页面的 wxss 样式
    // 和其他使用了 apply-shared 以及 share 属性的自定义组件

    
    styleIsolation: "shared"

  }

})

7.组件样式隔离(修改checkbox样式)

css 复制代码
/* components/custom-checkbox/custom-checkbox.wxss */



/* 复选框组件是公共组件 */
/* 以后需要再多个页面或者需要在多个项目中进行使用 */
/* 所以,需要先给复选框组件准备,设置一些默认样式 */
/* 如果在其他页面或者其他项目中使用的时候,发现样式不符合产品需求 */
/* 可以进行修改、对默认的样式进行修改 */

/* 1.需要给复选框设置默认样式 */
/* 需要先找到小程序给复选框提供的类名,通过小程序给提供的类名修改才可以 */
/* 需要先打开小程序开发文档,找到复选框文档,审查元素,进行查找 */

/* 在自定义组件中,不能直接修改复选框样式 */
/* 如果需要进行修改,需要设置 styleIsolation 才可以 */
/* shared:修改其他页面的样式、组件使用者的样式、以及其他使用了 share 以及 apply-share 的组件 */
/* 这时候,不是想要的结果 */
/* 需求是:只想影响当前组件,可以添加命名空间 */

/* 复选框没有选中时默认的样式 */
.custom-checkbox .wx-checkboxe-input {
  width: 24rpx !important;
  height: 24rpx !important;
  border-radius: 50% !important;
  border: 1px solid #fda007 !important;
  margin-top: -6rpx;
}

/* 复选框选中时默认的样式 */
.custom-checkbox .wx-checkedbox-input-checked {
  background-color: #fda007 !important;
}

/* 复选框选中时 ✔ 样式 */
.custom-checkbox .wx-checkboxe-input.wx-checkedbox-input-checked:before {
  font-size: 22rpx;
  color: #fff;
}

/* 2.组件使用者也能够修改默认的样式 */
html 复制代码
<!--index-->


<view class="custom">
  <custom-checkbox label="匿名提交" position="left">
    匿名提交 - 222
  </custom-checkbox>
</view>
css 复制代码
/**index.wxss**/


/* 组件使用者修改复选框的样式 */
.custom .custom-checkbox .wx-checkboxe-input {
  border: 1px solid  lightseagreen !important;
}

.custom .custom-checkbox .wx-checkedbox-input-checked {
  background-color: lightseagreen !important;
}

8.数据监听器observers

html 复制代码
<!--components/custom04/custom04.wxml-->

<view>{{ num }}</view>
<view>{{ count }}</view>
<view>{{ obj.name }}</view>
<view>{{ arr[1] }}</view>
<view>{{ label }}</view>
<button type="warn" plain bind:tap="updateData">更新数据</button>


<!--cate-->
<custom04 label="标题" />
javascript 复制代码
// components/custom04/custom04.js
Component({

  /**
   * 组件的属性列表
   */
  properties: {
    label: {
      type: String,
      value: '测试'
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    num: 10,
    count: 100,
    obj: { name: 'Tom', age: 10 },
    arr: [1, 2, 3]
  },

  // 用来监听数据已经属性是否发生了变化
  observers: {

    // key:需要监听的数据
    // value:就是一个回调换上,形参:最新的数据
    num:function (newNum) {
      // 对 data 中的数据进行监听,如果数据没有发生改变,监听器不会执行
      console.log(newNum)
    },

    // count:function (newCount) {
    //   console.log(newCount)
    // }

    // // 同时监听多个数据
    // 'num, count': function (newNum, newCount) {
    //   console.log(newNum, newCount);
    // }

    // // 支持监听属性以及内部数据的变化
    // 'obj.name': function (newName) {
    //   console.log(newName)
    // },

    // 'arr[1]': function (newItem) {
    //   console.log(newItem)
    // }

    // 使用通配符
    // 'obj.**': function (newObj) {
    //   console.log(newObj)
    // }

    label: function (newLabel) {
      // 只要组件使用者传递了数据,这个时候在监听器中就能获得传递的数据
      // 也就是说,监听器立即就执行了
      console.log(newLabel)
    }

  },

  /**
   * 组件的方法列表
   */
  methods: {

    // 更新数据
    updateData () {

      this.setData({
        num: this.data.num + 1,
        // count: this.data.count - 1
        // 'obj.name': 'jerry',
        // 'arr[1]': 666
        label: '最新的标题'
      })

    }

  }
})

9.组件通信

(1)父往子传值

javascript 复制代码
// components/custom-checkbox/custom-checkbox.js

properties: {
    // 复选框组件是公共组件 
    // 需要在多个页面或多个项目中进行使用
    // 在使用的时候,有的地方是希望默认是被选中的效果,有的地方希望默认是没有被选中的效果
    // 怎么处理呢?
    // 首先让复选框默认还是没有被选中的效果
    // 如果希望复选框默认被选中,这个时候传递属性(checked=true)到复选框组件
    checked: {
      type: Boolean,
      value: false
    }
  },

observers: {
    // 如果需要将 properties 中的数据赋值给 data
    // 可以使用 observers 进行处理
    checked: function (newChecked) {
      // console.log(newChecked)
      this.setData({
        isChecked: newChecked
      })
    }
  },

(2)子往父传值

html 复制代码
<!--cart-->

<view>{{ num }}</view>
<!-- 需要在自定义组件标签上通过 bind 方法绑定自定义事件,同时绑定事件处理函数 -->
<custom05 bind:myevent="getData" />



<!--components/custom05/custom05.wxml-->
<button type="primary" plain bind:tap="sendData">传递数据</button>
javascript 复制代码
// cart

Page({

  data: {
    num: ''
  },

  getData (event) {
    // 可以通过事件对象 .detail 获取子组件传递给父组件的数据
    // console.log(event)
    this.setData({
      num: event.detail
    })
  }

})





// components/custom05/custom05.js
Component({

  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    num: 100
  },

  /**
   * 组件的方法列表
   */
  methods: {

    // 将数据传递给父组件
    sendData () {

      // 如果需要将数据传递给父组件
      // 需要使用 triggerEvent 发射自定义事件
      // 第二个参数,是携带的参数
      this.triggerEvent('myevent',this.data.num)

    }

  }
})

(3)获取组件实例

html 复制代码
<!--index-->


<custom-checkbox
  label="我已阅读并同意 用户协议 和 隐私协议"
  position="right" 
  checked="{{ isChecked }}"
  class="child"
  id="child"
  bind:changechecked="getData"
>
  我已阅读并同意 用户协议 和 隐私协议 - 111
</custom-checkbox>

<view class="line"></view>

<view class="custom">
  <custom-checkbox label="匿名提交" position="left">
    匿名提交 - 222
  </custom-checkbox>
</view>

<button type="primary" plain bind:tap="getChild">获取子组件实例对象</button>
javascript 复制代码
// index


Page({

  data: {
    isChecked: true
  },

  getData (event) {
    console.log(event.detail)

    if (event.detail) {
      console.log('提交')
    } else {
      console.log('请同意协议')
    }
  },

  // 获取子组件的实例对象
  getChild () {

    // this.selectComponent 方法获取子组件实例对象
    // 获取实例对象以后,就能获取子组件所有的数据,也能调用组件的方法
    const res = this.selectComponent('.child')
    console.log(res.data.isChecked)

  }
})

10.组件生命周期

html 复制代码
<!--components/custom06/custom06.wxml-->
<!-- <text>components/custom06/custom06.wxml</text> -->

<view>{{ name }}</view>




<!--profile-->
<custom06 wx:if="{{ num === 1 }}" />

<button type="warn" bind:tap="handler">销毁自定义组件</button>
javascript 复制代码
// components/custom06/custom06.js
Component({

  data: {
    name: 'tom'
  },

  // 组件生命周期声明对象
  lifetimes: {

    // created:组件实例被创建好以后执行
    created () {
      console.log('组件 created')

      // 所以在 created 钩子函数中不能调用 setData
      // 可以给组件添加一些自定义的属性,可以通过 this 的方式进行添加
      this.test = '测试'
      // this.setData({
      //   name: 'jerry'
      // })
    },

    // attached:组件被初始化完毕,模板解析完成,已经把组件挂载到页面上
    attached () {
      console.log('组件 attached')
      console.log(this.test)

      // 一般页面中的交互会在 attached 钩子函数中进行实现
      this.setData({
        name: 'jerry'
      })
    },

    // detached:组件被销毁时触发执行
    detached () {
      console.log('组件 detached')
    }
  }

})





// profile.js
Page({

  data: {
    num: 1
  },

  handler () {
    this.setData({
      num: this.data.num + 1
    })
  }

})

11.组件所在页面的生命周期

javascript 复制代码
// components/custom06/custom06.js
Component({

  data: {
    name: 'tom'
  },


  // 组件所在页面的生命周期
  pageLifetimes: {

    // 监听组件所在页面的展示(后台切前台)状态
    show () {
      console.log('组件所在页面被展示')
    },

    // 监听组件所在页面的隐藏(前台切后台、点击 tabBar)状态
    hide () {
      console.log('组件所在页面被隐藏')
    }

  }

})

12.小程序生命周期总结

13.拓展

(1)使用Component构造页面

html 复制代码
<!--pages/detail/detail.wxml-->

<view>{{ name }}</view>

<button type="warn" plain bind:tap="updateName">更新 name</button>





<!--pages/profile/profile.wxml-->

<navigator url="/pages/detail/detail?id=10&title=测试">跳转到详情页面</navigator>
javascript 复制代码
//detail.js


Component({

  // 为什么需要使用 Component 方法构造页面
  // Component 方法功能比 Page 方法强大很多
  // 如果使用 Component 方法构造页面,可以实现更加复杂的页面逻辑开发

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

  properties: {
    id: String,
    title: String
  },

  data: {
    name: 'tom'
  },

  onLoad () {
    console.log('页面加载 - 1')
  },  

  methods: {

    onLoad (options) {
      // console.log('页面加载 - 2')
      // console.log(options)
      console.log(this.data.id)
      console.log(this.data.title)
    },  

    // 更新 name
    updateName () {
      this.setData({
        name: 'jerry'
      })
    }

  }

})

(2)组件复用机制 behaviors

html 复制代码
<!--components/custom08/custom08.wxml-->
<!-- <text>components/custom08/custom08.wxml</text> -->

<view>{{ label }}</view>
<view>{{ name }}</view>
<view>{{ obj.name }} - {{ obj.age }}</view>

<button type="primary" plain bind:tap="updateName">更新数据</button>
javascript 复制代码
// components/custom08/behavior.js
const behavior = Behavior({

  /**
   * 组件的属性列表
   */
  properties: {
    label: {
      type:String,
      value: '我已同意该协议'
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    name: 'tom',
    obj: {
      name: 'jerry'
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    updateName () {
      this.setData({
        name: 'jerry'
      })

      console.log('我是 behavior 内部的方法!!!')
    }
  },

  lifetimes: {
    attached () {
      console.log('我是 behavior 的生命周期函数~~~~~~~~~~~~~~~~~')
    }
  }

})

export default behavior





// components/custom08/custom08.js
import behavior from './behavior'

Component({

  behaviors: [behavior],

  // 在以后开发中,使用 behaviors 进行代码复用的时候
  // 组件 和 behaviors 可能存在相同的字段

  // 如果存在相同的 properties,就近原则,使用组件内部的数据
  properties: {
    label: {
      type: String,
      value: '匿名提交'
    }
  },

  // 如果存在相同的 data
  // 如果是对象类型,属性会进行合并
  // 如果不是对象类型的数据,展示的以组件内部为准
  data: {
    name: '组件中的 name',
    obj: {
      name: '组件中的 obj name',
      age: 100
    }
  },

  // 如果存在相同的方法,就近原则,使用组件内部的数据
  methods: {
    updateName () {
      console.log('我是组件内部的方法!!!')
    }
  },

  // 如果存在相同的生命周期函数,生命周期函数都会被触发
  lifetimes: {
    attached () {
      console.log('我是组件内部调用的生命周期函数!!!!')
    }
  }
  
})

(3)外部样式类

html 复制代码
<!--profile.wxml-->

<!-- 属性是在 externalClasses 里面定义的元素 -->
<!-- 属性值必须是一个类名 -->
<custom09 extend-class="my-class" />





<!--components/custom09/custom09.wxml-->
<!-- <text>components/custom09/custom09.wxml</text> -->

<!-- 在同一个节点上,如果存在外部样式类 和 普通样式类 -->
<!-- 两个类的优先级是未定义的 -->
<!-- 建议:在使用外部样式类时,样式需要通过 !important 添加权重 -->
<view class="extend-class box">通过外部样式类修改组件的样式</view>
css 复制代码
/* components/custom09/custom09.wxss */
.box {
  color: lightseagreen;
}




/* profile.wxss */
.my-class {
  color: lightsalmon !important;
}
javascript 复制代码
// components/custom09/custom09.js
Component({

  // 组件接受的外部样式类
  externalClasses: ['extend-class']
})

14.完善复选框案例以及总结自定义组件

如果 styleIsolation: 'shared',则 externalClasses 选项会失效

相关推荐
double_eggm11 小时前
5.微信小程序
小程序
梦想的颜色18 小时前
2026最新Claude Code 规范文件 CLAUDE.md 全面解析与超全模板
人工智能·小程序
double_eggm1 天前
微信小程序6
微信小程序·小程序
AI行业应用研究1 天前
破解活动统筹难题:会务小程序为活动组织提供全流程解决方案
小程序
万岳科技系统开发2 天前
直播电商APP搭建如何支持多门店与多主播模式
小程序·架构
游戏开发爱好者82 天前
iOS应用性能监控:Pre-Main与Main函数耗时分析及Time Profiler使用教程
android·ios·小程序·https·uni-app·iphone·webview
StarChainTech2 天前
先享后付,正在悄悄改变电商的“信任游戏”
大数据·人工智能·游戏·微信小程序·小程序·软件需求
小羊Yveesss2 天前
门店小程序外卖配送搭建实战:配送对接、运费策略与多门店调度方案
小程序·apache
tianxiaxue12 天前
企业微信与小程序互联互通
小程序·企业微信