速通-微信小程序 4Day

8 阅读21分钟

速通-微信小程序 4Day

速通-微信小程序-CSDN博客

速通-微信小程序 2Day-CSDN博客

速通-微信小程序 3Day-CSDN博客

紧接前文,搭配有助于快速,巩固/学习!话不多说开始!

经过前面几篇的学习,好简单,最起码对于做过前端Vue 开发,小程序前后端 so so easy!

哦对了,顺便推荐一下之前的VUE学习blog,此篇有很多知识概念何Vue高度类似;

自定义组件:

什么是组件:

小程序自定义组件Component 是运行在 小程序框架内 的独立功能单元

包含 结构WXML、样式WXSS、逻辑JS、配置JSON 四部分,与页面功能类似

但 体积更小、作用域更独立 专门用于封装可复用的 UI 模块

  • 如:按钮、导航栏、弹窗、商品卡片

  • 复杂页面:评分组件、轮播图组件

组件和页面的区别:

两者的本质差异在于 运行形态、注册方式和生命周期,以下是详细对比表格:

对比维度页面(Page)自定义组件(Component)
生命周期专属页面生命周期
onLoad/onShow/onReady
专属组件生命周期
created/attached/ready
文件结构必须包含 4 个文件:
.wxml/.wxss/.js/.json
可按需省略文件
如:无需样式可省略.wxss),核心是.js
注册方式app.jsonpages数组中注册在页面的 .json 通过
usingComponents 注册 不能注册到 app.json
路由能力支持 wx.navigateTo 等路由跳转无路由能力,不能通过路由跳转
运行形态独立的页面载体,可直接跳转访问;依附于页面/其他组件,无法直接跳转;
样式隔离全局样式 app.wxss 可覆盖页面样式默认样式隔离,组件样式仅作用于自身
数据通信无父子通信概念,数据通过 onLoad 接收支持父传子 properties
子传父 triggerEvent
  • 组件的 .json 文件中需要声明 "component": true 属性;

  • 组件的事件处理函数需要定义到 methods 节点中;

  • 组件的 .js 文件中调用的是 Component() 函数;

组件的创建\引用

创建自定义组件:

在项目中新建 components 文件夹,统一存放所有组件 再创建组件子文件夹,创建 4 个文件:

  • 在项目的根目录中,鼠标右键,创建 components -> 组件名 文件夹
  • 在新建的 components -> 组件名 文件夹上,鼠标右键,点击 新建 Component
  • 输入组件名称之后回车,会自动生成组件对应的 4 个文件,分别为 .js/.json/.wxml/.wxss
project
├── components
│   └── demo          // 组件名:demo组件
│       ├── demo.wxml // 结构
│       ├── demo.wxss // 样式(可选)
│       ├── demo.json // 配置(可选)
│       └── demo.js   // 逻辑(必选)

在这里插入图片描述

组件的引用:

组件的引用方式分为 局部引用全局引用,顾名思义:

  • 局部引用:组件只能在当前被引用的页面内使用;

  • 全局引用:组件可以在每个小程序页面中使用;

局部引用:

仅在 少数页面 使用的组件,如:详情页专属的评分组件,避免全局注册导致的资源冗余。

目标页面.json 中,通过 usingComponents 声明组件别名与路径:

{
  "usingComponents": {
	// 键:组件别名(自定义) : 值:组件绝对路径;
    "demo1": "/components/demo1/demo1" 
  }
}

目标页面: 直接通过 组件别名 在 WXML 中调用,传递属性即可:

<view>
局部引用: 
  <demo1></demo1>
</view>

在这里插入图片描述

全局引用:

小程序 所有页面 都会用到的基础组件,如:导航栏、空状态页、加载动画、评分星标

在小程序根目录的 app.json 中,通过 usingComponents 全局注册组件:

{
  "pages": ["pages/home/home", "pages/message/message", "pages/.../..."],
  "usingComponents": {
    "empty": "/components/demo2/demo2", // 全局空状态组件
  }
}

直接在 任意页面 的 WXML 中调用组件别名即可:

<view>
全局引用: 
  <demo2></demo2>
</view>

在这里插入图片描述

组件样式隔离🧱:

默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的 UI 结构:

页面的 WXSS 样式,包括全局 app.wxss 不会影响组件内部

样式隔离配置:

在组件的 .json 文件中,通过 styleIsolation 属性可自定义隔离规则,支持以下三种取值:

配置值页面样式对组件的影响
isolated 默认仅组件内部,无影响(完全隔离)
绝大多数场景,推荐使用,保证组件独立性
apply-shared仅组件内部,页面样式会影响组件,组件样式不会影响页面
需复用页面全局样式的场景,如:统一字体、主题色
shared组件内部 + 页面,组件与页面样式互相影响 双向污染
特殊场景:如:组件需完全继承页面样式, 慎用

修改组件的样式隔离选项:

**方式一:**在组件的 .json 文件中新增如下配置;

{
  "component": true,
  "styleIsolation": "isolated"	// 默认值,可省略
}

方式二: 在组件的 .js 文件中新增如下配置;

Component({
    options: {
       styleIsolation: 'isolated'
    }
})

😎😎😎实际开发中,一般都是,方式一,默认配置 isolated,更方便;

在这里插入图片描述

注意事项:

注意:组件 和 页面最终会合并成一个页面,所以在最外层声明的样式,会传递到内层;

禁止使用 id 选择器、属性选择器、标签选择器,默认隔离模式下,这些选择器不会生效;

全局样式 app.wxss,默认不会影响组件: 若需让组件继承全局样式,

建议通过 apply-shared 而非 shared,避免双向污染;

数据\方法\属性:

小程序自定义组件的核心能力由

data 内部数据、methods 方法、properties 外部属性

三部分构成,分别负责组件的:状态存储、逻辑处理、外部通信;

data 数据

定义:组件的 私有内部数据,仅组件自身可读写,外部无法直接修改

作用:存储组件的临时状态、渲染所需的本地数据,如:交互状态、计算结果;

<text>组件的 count: {{count}}</text>
Component({ 
  /** 组件的初始数据 */
  data: { 
    count: 0
  },
})

在这里插入图片描述

menthods 方法

定义:组件的 逻辑处理函数集合,包括事件处理、业务逻辑等;

作用:处理组件的交互事件、数据计算、通信逻辑等;

Demo: 定义一个函数 addcount 添加 count 值;

<text>组件的 count: {{count}}</text>
<button bind:tap="addconut" >count +1 按钮</button>
Component({
  /*** 组件的属性列表 */
  properties: {  },
  /** 组件的初始数据 */
  data: { 
    count: 0
  },
  /*** 组件的方法列表 */
  methods: { 
    addconut(){
      this.setData({ count: this.data.count+1 })
    },
  }
})

在这里插入图片描述

properties 属性:

定义:组件的 外部输入属性,用于接收父组件传递的数据,是父组件与子组件通信的核心方式。

作用:接收外部参数,动态配置组件的行为和展示,如:初始值、开关状态;

Demo: 在调用组件时候,传递一个最大值,addcount 不允许超过 max

调用组件传递值:max

<view>
  <text class="styled" >全局引用: </text>
  <demo2 max="10" ></demo2>
</view>

组件方接受,并处理不允许超过最大值: 接收父组件传递的参数,支持类型校验type 和默认值value

  • type 支持的类型包括:String/Number/Boolean/Object/Array
  • 父组件未传递参数时,组件自动使用 value 作为属性默认值;
Component({
  /*** 组件的属性列表 */
  properties: {
    //方式一: 完整定义(需指定默认值时使用)
    max: {
      type: Number,   // 数据类型(Number/String/Boolean等)
      value: 10       // 默认值 10
    }
    //方式二: 简化定义(无需默认值时使用)
    // max: Number
  },
  /** 组件的初始数据 */
  data: { 
    count: 0
  },
  /*** 组件的方法列表 */
  methods: { 
    addconut(){
      if(this.data.count>=this.properties.max){ return; }
      this.setData({ count: this.data.count+1 })
    },
  }
})

在这里插入图片描述 data 和 properties 的区别

小程序组件的 dataproperties 实际上是指向 同一个内部数据对象

this.data === this.properties 的结果为 true 同一个内存对象

尽管技术上可以互相读写,但需遵守以下规范以提升代码可维护性:

  • properties 更倾向于存储外界传递到组件中的数据
  • data 更倾向于存储组件的私有数据

数据监听器📼:

❓什么是数据监听:

小程序组件的 数据监听器 是通过 observers字段定义的回调机制,作用是:

  • 监测组件内 data(私有数据)或 properties(外部属性)的变化;
  • 当指定数据发生改变时,自动触发预设的回调函数
  • 类似于 vue 中的 watch 侦听器;

数据监听基本使用:

在组件的 Component 构造器中,通过 observers 字段定义监听器,支持多种监听规则:

Demo: 数据监听器实现 n1、n2 自增后自动计算总和 sum 的功能;

  • 交互方法addN1/addN2 通过 this.setData修改n1/n2的值,触发数据变化;
  • 数据监听器observers监听n1n2的变化,当任意一个值更新时,自动计算 sum 并同步到视图
<!-- 组件的WXML结构 -->
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button size="mini" bindtap="addN1">n1自增</button>
<button size="mini" bindtap="addN2">n2自增</button>
Component({
  data: { n1: 0, n2: 0, sum: 0 },
  methods: {
    addN1() { this.setData({ n1: this.data.n1 + 1 }); },
    addN2() { this.setData({ n2: this.data.n2 + 1 }); }
  },
  // 监听n1和n2的变化,自动计算sum
  observers: {
    'n1, n2': function(n1, n2) {
      this.setData({ sum: n1 + n2 });
    }
  }
})

在这里插入图片描述

监听对象属性的变化:

小程序数据监听器支持 监听对象中单个或多个属性的变化,通过指定 对象.属性 的路径语法;

Component({
  observers: {
    // 语法: "对象.属性A,对象.属性B"(多个属性用逗号分隔)
    "对象.属性A,对象.属性B": function(objA, objB) {
      // 回调参数顺序与监听的属性顺序一致,接收对应属性的新值
	  // 触发此监听器的 3种情况:
	  //[为属性A赋值] 使用 setData 设置 this.data.对象.属性A 时触发
	  //[为属性B赋值] 使用 setData 设置 this.data.对象.属性B 时触发
      //[直接为对象赋值] 使用 setData 设置 this.data.对象 时触发
    }
  }
})

数据监听 - 案例: 动态 RGB 颜色选择器组件,通过按钮调整 R/G/B 颜色通道值;

利用数据监听器自动同步颜色展示区域的背景色与数值;

<view style="background-color: rgb({{fullColor}});" class="colorBox">
  颜色值:{{fullColor}}
</view>
<button size="mini" bindtap="changeR" type="default">R</button>
<button size="mini" bindtap="changeG" type="primary">G</button>
<button size="mini" bindtap="changeB" type="warn">B</button>
Component({
  // 1. 初始数据:RGB对象+颜色值字符串
  data: {
    rgb: { r: 0, g: 0, b: 0 },
    fullColor: '0, 0, 0' // 用于渲染背景色的字符串
  },

  // 2. 事件处理函数:调整RGB通道值(最大255)
  methods: {
    // 调整R G B通道
    // 每个按钮绑定对应的changeX方法,通过 this.setData 修改rgb对象的对应属性
    // 用三元运算符限制通道值不超过 255 RGB 颜色通道的最大值)
    changeR() { this.setData({ 'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5 }); },
    changeG() { this.setData({ 'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5 }); },
    changeB() { this.setData({ 'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5 }); }
  },

  // 3. 数据监听器(方式1:监听指定属性)
  observers: {
    // 监听rgb对象的r、g、b属性变化
    'rgb.r, rgb.g, rgb.b': function(r, g, b) { this.setData({ fullColor: `${r}, ${g}, ${b}` }); }

    // 方式2:通配符监听对象所有属性(属性过多时简化写法)
    // 'rgb.**': function(obj) {
    //   this.setData({
    //     fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
    //   });
    // }
  }
})

在这里插入图片描述

数据监听器的两种用法:

  • 方式一: '对象.属性A, 对象.属性B',精准监听指定属性,

    回调参数顺序与监听的属性顺序一致,直接获取对应属性的新值

  • 方式二: '对象.**',监听对象的 所有子属性变化, 回调参数是整个对象,适用于属性较多的场景;

纯数据字段

什么是纯数据字段:

纯数据字段指的是那些,不用于界面渲染的 data 字段

例如:有些情况下,某些 data 中的字段,既不会展示在界面上,也不会传递给其他组件

仅仅在当前组件内部使用,这种特性的字段适合被设置为纯数据字段,有助于提升页面更新的性能;

配置纯数据字段:

通过组件 Component 构造器的 options 节点,

指定pureDataPattern正则表达式,匹配该规则的 data 字段会被标记为 纯数据字段

Demo案例: 将之前案例中的 rgb(仅内部计算用,不直接渲染)改造为纯数据字段 _rgb

Component({
  // 1. 配置纯数据字段规则(下划线开头)
  options: {
    pureDataPattern: /^_/
  },
  // 初始数据:RGB对象+颜色值字符串
  data: {
    // 2. 将原rgb改为纯数据字段_rgb
    _rgb: { r: 0, g: 0, b: 0 },
    fullColor: '0, 0, 0' // 用于渲染背景色的字符串
  },

  // 3. 事件处理:修改纯数据字段_rgb的属性
  // 事件处理函数:调整RGB通道值(最大255)
  methods: {
    // 调整R G B通道
    // 每个按钮绑定对应的changeX方法,通过 this.setData 修改rgb对象的对应属性
    // 用三元运算符限制通道值不超过 255 RGB 颜色通道的最大值)
    changeR() { this.setData({ '_rgb.r': this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5 }); },
    changeG() { this.setData({ '_rgb.g': this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5 }); },
    changeB() { this.setData({ '_rgb.b': this.data._rgb.b + 5 > 255 ? 255 : this.data._rgb.b + 5 }); }
  },

  // 4. 数据监听器:监听纯数据字段_rgb的变化
  // 数据监听器(方式1:监听指定属性)
  observers: {
    // 监听rgb对象的r、g、b属性变化
    // '_rgb.r, _rgb.g, _rgb.b': function(r, g, b) { this.setData({ fullColor: `${r}, ${g}, ${b}` }); }
    // 方式2:通配符监听对象所有属性(属性过多时简化写法)
    '_rgb.**': function(obj) {
      this.setData({
        fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
      });
    }
  }
})
  • 配置纯数据字段规则: _下划线开头,将原 rgb 改为纯数据字段 _rgb
  • 事件处理:修改纯数据字段 _rgb 的属性,数据监听器:监听纯数据字段 _rgb 的变化;

组件的生命周期🧬

小程序组件的生命周期分为:

  • 组件自身生命周期: 控制组件自身的 创建、初始化、销毁
  • 组件所在页面生命周期: 响应控制组件,所在页面状态变化;

二者通过不同节点配置,是组件逻辑初始化、资源清理的核心机制;

组件生命周期:

组件自身生命周期控制组件从 创建 到 销毁 的过程,通过 lifetimes 节点配置;

生命周期参数描述说明
created组件实例刚被创建时执行,
此时不能调用 setData,仅用于给组件添加自定义属性
attached组件实例进入页面节点树时执行,
this.data已初始化,适合做初始化工作 如: 请求数据
detached组件实例被从页面节点树移除时执行,适合做清理工作如: 清除定时器
ready组件在视图层布局完成后执行,可操作 DOM 节点
moved组件实例被移动到节点树另一个位置时执行 极少用
errorObject Error组件方法抛出错误时执行,用于错误捕获

lifetimes 节点:

推荐在lifetimes节点中声明生命周期函数,优先级高于 直接定义在 Component 第一级参数:

Component({
  // 推荐方式:lifetimes节点
  lifetimes: {
	created() { /** 给组件添加自定义属性 */ },
    attached() { /** 初始化:请求组件初始数据 */ },
    detached() {
      // 清理:清除定时器
      clearInterval(this.timer);
    }
  },
    
  // 旧方式(不推荐)
  // attached() {},
  // detached() {}
})

组件>页面生命周期

当组件行为 依赖页面状态变化时触发 如:页面展示时组件更新数据;

组件所在页面的生命周期函数,会在 组件所在页面的对应生命周期触发时 执行,

用于实现 页面状态变化→组件行为同步 的联动逻辑,如:页面切回前台时,组件刷新数据;

生命周期函数参数描述
show组件所在页面被展示时执行(如页面从后台切回前台)
hide组件所在页面被隐藏时执行(如页面切到后台)
resizeObject Size组件所在页面尺寸变化时执行(如屏幕旋转)

pageLifetimes 节点

页面生命周期函数需定义在 pageLifetimes 节点中:

Component({
  pageLifetimes: {
    show() { /** 页面展示时,执行组件逻辑(如刷新数据) */ },
    hide() { /** 页面隐藏时,暂停组件任务(如暂停播放)*/ },
    resize(size) { /** 页面尺寸变化时,调整组件布局 */ }
  }
})

插槽🔌

插槽是小程序自定义组件的 内容占位机制

通过 <slot> 节点在组件中 预留位置,由,组件使用者自定义填充内容,

让组件兼具 封装性灵活性 既保留组件的基础结构,又支持使用者自定义部分内容:

单个插槽:

小程序组件默认仅支持 1 个插槽,称为 单个插槽,是最基础的插槽用法:

组件中定义插槽(组件 WXML)

  • 在组件的 WXML 中添加 <slot> 节点,作为内容占位符:
  • 组件使用者在引用组件时 ,在组件标签内编写的 WXML 结构,会自动填充到 <slot> 的位置;
<view>
  <!-- 组件的固定结构 -->
  <view>demo4slot 组件内部↓</view>
  <!-- 插槽:使用者自定义的内容会填充到这里 -->
  <slot></slot>
  <view>demo4slot 组件内部↑</view>
</view>

调用接受方: 在引用组件的标签内,直接编写需要填充的 WXML 结构,会自动替换组件中的<slot>

<!-- 引用: 单slot插槽组件 -->
<demo4slot>
    <view>主页引用demoslot插槽组件1</view>
    <view>主页引用demoslot插槽组件2</view>
	<view>主页引用demoslot插槽组件3</view>
</demo4slot>

在这里插入图片描述

启用多个插槽:

默认不支持多个插槽,需手动启用后,可在组件中定义 多个带名称的插槽,实现 多区域内容自定义

启用多个插槽 组件 JS 在组件的 Component 构造器中,通过 options 节点设置

multipleSlots: true,启用多插槽支持🔌🔌🔌;

组件.JS 文件配置📄

// 组件的JS
Component({
  options: {
    multipleSlots: true // 启用多插槽支持
  },
  properties: {},
  methods: {},
  data:{}
})

组件中定义多插槽 组件 WXML<slot>添加 name 属性区分不同插槽:

<view style="border: 2px solid #f60;">
  <!-- 插槽1:name为“header” -->
  <slot name="header"></slot>

  <!-- 组件的固定内容 -->
  <view>组件的固定的主体区域</view>
  
  <!-- 插槽2:name为“footer” -->
  <slot name="footer"></slot>
</view>

使用者填充多插槽内容: 在引用组件时,通过 slot 属性指定内容对应的插槽名称:

<!-- 引用: 多slot插槽组件 -->
<demo5slots>
    <!-- 填充到name="header"的插槽 -->
    <view slot="header" style="background-color: gold;">自定义头部内容1</view>
    <view slot="header" style="background-color: gold;">自定义头部内容2</view>

    <!-- 填充到name="footer"的插槽 -->
    <view slot="footer" class="custom-footer">自定义底部内容1</view>
    <view slot="footer" class="custom-footer">自定义底部内容2</view>

    <view slot="header" style="background-color: gold;">自定义头部内容3</view>
    <view slot="header" style="background-color: gold;">自定义头部内容4</view>
</demo5slots>

在这里插入图片描述

  • 单个插槽无 name:单个插槽不需要设置name,使用者的内容会默认填充;

  • 多插槽需启用:必须在组件 JS 的 options 中设置 multipleSlots: true ,否则多插槽不生效;

  • 插槽的作用域:插槽中使用的数据,是 组件使用者的作用域 而非组件的作用域

    即插槽内可直接使用,使用者页面/父组件的 data 数据;

父子组件通信👨‍👦

小程序父子组件通信是组件协作的核心机制,包含:

属性绑定 父→子、事件绑定 子→父、 获取组件实例 父直接操作子 三种方式,覆盖不同场景通信需求;

通信方式数据流向核心用途
属性绑定父→子JSON 兼容数据类型:数字、字符串、等 …
父向子传递配置参数、初始数据;
事件绑定子→父任意类型:对象、函数、等 …
子向父传递交互结果、状态变化;
获取组件实例父→子(直接操作)父直接调用子组件:方法、修改数据;

属性绑定:父-子

通过父组件给子组件设置属性,子组件在 properties 中声明后使用,实现 父向子传递数据

  • 父组件定义数据:在父组件的data中声明要传递的数据,
  • 在引用子组件的标签中,通过 属性名="{{数据}}" 传递;
  • 在子组件的 properties 中声明对应属性 指定类型
  • 在子组件的 WXML/JS 中直接使用该属性;

父组件:JS

Page({
  data: { count: 1 }, // 要传递给子组件的数据
  addcount(){ this.setData({count: this.data.count+1 }) } //父组件 count++ 更新;
})

父组件:wxml

<view>
全局引用: 
  <view>父组件中,count值为: {{count}}</view>
  <button bind:tap="addcount" >父组件 count++</button>
  <demo6zjParam1 Zcount="{{count}}" ></demo6zjParam1>
</view>

子组件:JS

// 子组件JS
Component({
  properties: { Zcount: Number  }
})

子组件:wxml

<!-- 子组件WXML -->
<text>子组件中 获取 父组件 count 值为: {{Zcount}}</text>

父组件的 count 值会同步传递到子组件 Zcount,父组件修改 count 时,子组件会自动更新 Zcount

在这里插入图片描述

在这里插入图片描述

事件绑定:子-父

通过 父组件绑定自定义事件 + 子组件触发事件 的方式,实现子向父传递数据,支持任意类型数据;

  • 父组件定义处理函数:父组件中定义:接收子组件数据的函数

    在引用子组件的标签中,通过 bind:自定义事件名="处理函数" 绑定

  • 子组件触发事件:子组件中通过 this.triggerEvent('自定义事件名', {参数对象}) 触发事件并传参;

  • 父组件接收数据:父组件的处理函数通过 e.detail 获取子组件传递的参数;

父组件:JS

Page({
  data: { count: 1 },
  //父组件 count++ 更新;
  addcount(){ this.setData({count: this.data.count+1 }) }, 
  // 接收子组件数据的处理函数
  syncCount(e){
    console.log("通过e.detail获取子组件传递的参数");
    this.setData({ count: e.detail.value });
  }
})

父组件:wxml

<view>
全局引用: 子传父
  <view>父组件中,count值为: {{count}}</view>
  <demo7zjParam2 count="{{count}}" bind:sync="syncCount"></demo7zjParam2>
</view>

子组件:JS

// 子组件JS
Component({
  properties: { count: Number },
  methods: {
    addCount() {
      console.log("调用: 子组件 count ++");
      this.setData({ count: this.properties.count + 1 });
      this.triggerEvent('sync', { value: this.properties.count }); // 触发自定义事件,向父组件传参
    }
  }
})

子组件:wxml

<!-- 子组件WXML -->
<text>子组件中,count值为:{{count}}</text>
<button bindtap="addCount">子组件 count ++</button>

在这里插入图片描述

点击子组件的 +1 按钮,子组件的count增加,

同时通过 triggerEvent 将新值传递给父组件,父组件的 count 同步更新;

获取组件实例:

父组件通过 this.selectComponent(选择器) 获取子组件实例,

直接调用子组件的方法、修改其数据,适用于需要 父主动控制子组件 的场景;

  • 子组件加标识:在子组件标签中添加 classid(作为选择器)

  • 父组件获取实例:父组件中通过 this.selectComponent('选择器') 获取子组件实例;

    父组件操作子组件:调用子组件的方法、修改其数据;

修改上述代码: ==父组件.JS==

Page({
  data: { count: 1 },
  //父组件 count++ 更新;
  addcount(){ this.setData({count: this.data.count+1 }) }, 
  // 接收子组件数据的处理函数
  syncCount(e){
    console.log("通过e.detail获取子组件传递的参数");
    this.setData({ count: e.detail.value });
  },
  // 获取子组件实例,调用子组件count++
  getChild(){
    console.log("通过class选择器获取子组件实例");
    const child = this.selectComponent('.customA');
    // 直接调用子组件的方法
    child.addCount();
  },
})

父组件:wxml

<view>
全局引用: 获取组件实例
  <view>父组件中,count值为: {{count}}</view>
  <demo7zjParam2 count="{{count}}" bind:sync="syncCount" class="customA" ></demo7zjParam2>
  <button bindtap="getChild">获取子组件实例,调用子组件count++</button>
</view>

在这里插入图片描述

behavious

behaviors 是小程序中 实现组件间代码共享 的特性

功能类似 Vue.js 的 mixins,可让多个组件复用同一套属性、数据、方法与生命周期逻辑

behaviors 的核心作用是组件间代码复用: 一个 behavior 可封装属性、数据、方法、生命周期函数等逻辑;

  • 多个组件可引用同一个 behavior,共享其封装的逻辑,

  • 组件引用 behavior 后,behavior 的内容会 合并到组件自身的配置中;

  • 单个组件可以引用 多个 behavior,behavior 自身也可以引用其他 behavior 支持嵌套复用

创建 behavior: Behavior(Object object) 方法创建 behavior 实例,并导出供组件使用,示例如下:

// 定义并导出behavior(如behaviors/my-behavior.js)
module.exports = Behavior({
  // 属性节点(同组件的properties)
  properties: {},
  // 私有数据节点(同组件的data)
  data: { username: 'zs' },
  // 方法/事件处理函数节点(同组件的methods)
  methods: {},
  // 生命周期函数(同组件的生命周期)
  created() {},
  attached() {}
  // 其他节点...
})

导入并使用 behavior: 组件需通过 require 导入 behavior,并挂载到 behaviors 数组中;

// 组件的JS文件
// 1. 导入behavior
const myBehavior = require("../../behaviors/my-behavior")

Component({
  // 2. 挂载behavior到behaviors数组
  behaviors: [myBehavior],
  
  // 组件自身的其他配置(可与behavior的内容合并)
  properties: {},
  data: {},
  methods: {}
})

在这里插入图片描述

behavior 支持的节点

可用节点类型是否必填描述
behaviorsString Array引用其他 behavior
propertiesObject Map同组件的属性配置
dataObject同组件的私有数据
methodsObject同组件的方法 / 事件处理函数
createdFunction生命周期函数(组件创建时)
attachedFunction生命周期函数(组件挂载时)
readyFunction生命周期函数(布局完成时)
movedFunction生命周期函数(组件移动时)
detachedFunction生命周期函数(组件销毁时)

同名字段的覆盖 / 组合规则

当组件与引用的 behavior 包含同名字段时,会按以下类别处理 详细规则需参考微信官方文档

  • 同名数据字段(data):组件自身的 data 会覆盖 behavior 的 data;

  • 同名属性(properties)/ 方法(methods):组件自身的定义会覆盖 behavior 的定义;

  • 同名生命周期函数:组件 与 behavior生命周期函数会 按顺序依次执行 behavior函数先执行

相关文档

黑马—小程序简介_哔哩哔哩_bilibili 对应:Day4 天内容!