微信小程序-父子组件通信

简介: 微信小程序可有意思了

概念

在微信小程序中,子组件向父组件传递数据可以通过自定义事件的方式实现。以下是子传父的通信步骤:

  1. 在子组件中,使用 triggerEvent 方法触发自定义事件,并携带需要传递的数据。示例如下:
// 子组件的.js文件
Component({
   
  // ...
  methods: {
   
    sendDataToParent() {
   
      const data = 'Hello, parent!'; // 要传递给父组件的数据
      this.triggerEvent('customEventName', data); // 触发自定义事件并传递数据
    },
  },
});
  1. 在父组件中,使用 bind:customEventName 绑定子组件触发的自定义事件,并在对应处理函数中获取子组件传递的数据。示例如下:
<!-- 父组件的.wxml文件 -->
<child-component bind:customEventName="handleChildData"></child-component>
// 父组件的.js文件
Page({
   
  // ...
  handleChildData(event) {
   
    const data = event.detail; // 获取子组件传递的数据
    console.log(data); // 处理子组件传递的数据
  },
});

当子组件调用 sendDataToParent 方法时,将会触发自定义事件 customEventName,并将数据传递给父组件。父组件通过 handleChildData 函数来处理子组件传递的数据。

通过这种方式,子组件就能将数据传递给父组件,实现了子传父的通信。

在微信小程序中,父组件向子组件传递数据可以通过属性传递的方式实现。以下是父传子的通信步骤:

  1. 在父组件中,在使用子组件的地方,通过属性将数据传递给子组件。示例如下:
<!-- 父组件的.wxml文件 -->
<child-component data="{
    {dataFromParent}}"></child-component>
// 父组件的.js文件
Page({
   
  data: {
   
    dataFromParent: 'Hello, child!',  // 要传递给子组件的数据
  },
});
  1. 在子组件中,可以通过 properties 字段定义接收父组件传递数据的属性,并在需要的地方使用该属性。示例如下:
// 子组件的.js文件
Component({
   
  properties: {
   
    data: String,  // 定义接收数据的属性
  },
  // ...
});
<!-- 子组件的.wxml文件 -->
<view>{
  {data}}</view> <!-- 在子组件中使用父组件传递的数据 -->

父组件通过将 dataFromParent 数据传递给子组件的 data 属性,子组件可以接收到父组件传递的数据并在需要的地方使用。

通过这种方式,父组件就能将数据传递给子组件,实现了父传子的通信。

实战

消息通知系统:在一个消息通知系统中,父组件是消息列表,子组件是单个消息。父组件可以向子组件传递需要展示的消息内容,子组件负责展示该消息并提供交互功能(如标记已读)

<!-- 父组件的.wxml文件 -->
<view>
  <message-list messages="{
    {messages}}" bind:markRead="onMarkRead"></message-list>
</view>
// 父组件的.js文件
Page({
   
  data: {
   
    messages: [
      {
   
        id: 1,
        title: "消息标题 1",
        content: "消息内容 1",
        isRead: false
      },
      {
   
        id: 2,
        title: "消息标题 2",
        content: "消息内容 2",
        isRead: false
      }
    ]
  },
  onMarkRead(e) {
   
    const messageId = e.detail;
    // 标记消息为已读
    const messages = this.data.messages.map(item => {
   
      if (item.id === messageId) {
   
        item.isRead = true;
      }
      return item;
    });
    this.setData({
    messages });
    console.log(`已标记消息 ${
     messageId} 为已读`);
  }
});
// 子组件的.js文件
Component({
   
  properties: {
   
    message: Object,
  },
  methods: {
   
    markRead() {
   
      const {
    id } = this.properties.message;
      // 触发标记已读事件
      this.triggerEvent('markRead', id);
    },
  }
});
<!-- 子组件的.wxml文件 -->
<view>
  <view>
    <text>{
  {message.title}}</text>
    <text>{
  {message.content}}</text>
  </view>
  <button wx:if="{
    {!message.isRead}}" bind:tap="markRead">标记已读</button>
</view>

如上,父组件通过属性 messages 将消息列表传递给子组件 message-list。子组件接收到消息后,根据每个消息的内容展示相应的标题和内容,并提供标记已读的按钮。

点击子组件的「标记已读」按钮时,子组件触发 markRead 事件,并将消息的 id 作为参数传递给父组件。父组件接收到事件后,根据消息的 id 更新相应消息的状态为已读。

同时也可以在 onMarkRead 方法中编写处理已读操作的逻辑,例如向后端发送请求更新消息状态。

多层级导航菜单:在一个多层级导航菜单中,父组件是一级菜单,子组件是二级菜单。父组件可以向子组件传递选中的一级菜单项,在子组件中展示对应的二级菜单。

<!-- 父组件的.wxml文件 -->
<view>
  <menu-list menus="{
    {menus}}" bind:selectMenu="onSelectMenu"></menu-list>
</view>
// 父组件的.js文件
Page({
   
  data: {
   
    menus: [
      {
   
        id: 1,
        name: "菜单项 1",
        subMenus: [
          {
   
            id: 11,
            name: "二级菜单项 1-1"
          },
          {
   
            id: 12,
            name: "二级菜单项 1-2"
          }
        ]
      },
      {
   
        id: 2,
        name: "菜单项 2",
        subMenus: [
          {
   
            id: 21,
            name: "二级菜单项 2-1"
          },
          {
   
            id: 22,
            name: "二级菜单项 2-2"
          }
        ]
      }
    ],
    selectedMenuId: null
  },
  onSelectMenu(e) {
   
    const menuId = e.detail;
    this.setData({
    selectedMenuId: menuId });
    console.log(`选中一级菜单 ${
     menuId}`);
  }
});
// 子组件的.js文件
Component({
   
  properties: {
   
    menus: Array
  },
  methods: {
   
    selectSubMenu(e) {
   
      const menuId = e.currentTarget.dataset.menuid;
      // 触发选中菜单事件
      this.triggerEvent("selectMenu", menuId);
    }
  }
});
<!-- 子组件的.wxml文件 -->
<view>
  <view wx:for="{
    {menus}}" wx:key="{
    {index}}" bind:tap="selectSubMenu" data-menuid="{
    {item.id}}">
    <text>{
  {item.name}}</text>
  </view>
</view>

如上,父组件通过属性 menus 将一级菜单传递给子组件 menu-list。子组件接收到菜单后,根据每个菜单项的内容展示菜单名称。

点击子组件的菜单项时,子组件触发 selectMenu 事件,并将菜单的 id 作为参数传递给父组件。父组件接收到事件后,更新选中的一级菜单项。

同时也可以在 onSelectMenu 方法中编写处理菜单选中操作的逻辑,例如根据选中的菜单项加载对应的二级菜单。

电子商务平台:在一个电子商务平台中,父组件是商品列表,子组件是商品卡片。父组件可以向子组件传递商品信息,以便在子组件上展示商品名称、价格等详细信息。

<!-- 父组件的.wxml文件 -->
<view>
  <product-list products="{
    {products}}"></product-list>
</view>
// 父组件的.js文件
Page({
   
  data: {
   
    products: [
      {
   
        id: 1,
        name: "商品 1",
        price: 100,
        image: "image_url_1"
      },
      {
   
        id: 2,
        name: "商品 2",
        price: 200,
        image: "image_url_2"
      }
    ]
  }
});
// 子组件的.js文件
Component({
   
  properties: {
   
    products: Array
  }
});
<!-- 子组件的.wxml文件 -->
<view>
  <view wx:for="{
    {products}}" wx:key="{
    {index}}">
    <image src="{
    {item.image}}"></image>
    <text>{
  {item.name}}</text>
    <text>价格:{
  {item.price}}</text>
  </view>
</view>

如上,父组件通过属性 products 将商品列表传递给子组件 product-list。子组件接收到商品列表后,根据每个商品的信息展示商品名称、价格和图片等详细信息。

也可以根据实际需求,在子组件的模板文件中展示更多的商品信息,比如商品描述、评分等。

表单验证:在一个表单验证页面中,父组件是表单,子组件是各个表单字段。父组件可以将验证规则传递给子组件,子组件根据规则进行实时验证并将验证结果返回给父组件进行整体表单验证。

<!-- 父组件的.wxml文件 -->
<view>
  <form>
    <form-field name="username" label="用户名" rules="{
    {usernameRules}}" bind:validate="onValidate"></form-field>
    <form-field name="password" label="密码" rules="{
    {passwordRules}}" bind:validate="onValidate"></form-field>
    <button bind:tap="submitForm">提交</button>
  </form>
</view>
// 父组件的.js文件
Page({
   
  data: {
   
    usernameRules: [
      {
   
        required: true,
        message: "请输入用户名"
      },
      {
   
        min: 6,
        max: 20,
        message: "用户名长度在6-20个字符之间"
      }
    ],
    passwordRules: [
      {
   
        required: true,
        message: "请输入密码"
      },
      {
   
        min: 8,
        message: "密码长度至少8个字符"
      }
    ]
  },
  onValidate(e) {
   
    const {
    name, valid } = e.detail;
    console.log(`${name} 字段验证结果为: ${valid}`);
    // 根据具体情况处理验证结果,比如更新数据或显示错误提示等
  },
  submitForm() {
   
    // 在这里可以进行整体表单的验证逻辑,根据各字段的验证结果进行处理
    // 若全部字段验证通过,则执行表单提交操作
  }
});
// 子组件的.js文件
Component({
   
  properties: {
   
    name: String,
    label: String,
    rules: Array
  },
  methods: {
   
    validateField(value) {
   
      const rules = this.data.rules;
      let valid = true;
      let message = "";

      for (let i = 0; i < rules.length; i++) {
   
        const rule = rules[i];

        if (rule.required && !value) {
   
          valid = false;
          message = rule.message;
          break;
        }

        if (rule.min && value.length < rule.min) {
   
          valid = false;
          message = rule.message;
          break;
        }

        if (rule.max && value.length > rule.max) {
   
          valid = false;
          message = rule.message;
          break;
        }
      }

      this.triggerEvent("validate", {
    name: this.data.name, valid, message });
    },
    onInput(e) {
   
      const value = e.detail.value;
      this.validateField(value);
    }
  }
});
<!-- 子组件的.wxml文件 -->
<view>
  <text>{
  {label}}</text>
  <input bindinput="onInput"></input>
</view>

如上,父组件定义了两个表单字段的验证规则 usernameRules 和 passwordRules,并将这些规则传递给子组件 form-field。子组件接收到规则后,根据用户输入的值实时进行验证,并将验证结果通过 validate 事件返回给父组件。

父组件可以根据接收到的验证结果进行相应的处理,比如更新数据或显示错误提示等。当用户点击提交按钮时,可以执行整体表单的验证逻辑,根据各字段的验证结果决定是否执行表单提交操作。

视频播放器:在一个视频播放器页面中,父组件是播放器控制条,子组件是视频播放器区域。父组件可以向子组件传递视频播放状态和进度,子组件根据传递的数据进行相应的播放操作。

<!-- 父组件的.wxml文件 -->
<view>
  <video-controls bind:play="playVideo" bind:pause="pauseVideo" bind:seek="seekVideo" bind:timeupdate="updateProgress"></video-controls>
  <video-player src="{
    {videoSrc}}" bind:ended="videoEnded"></video-player>
</view>
// 父组件的.js文件
Page({
   
  data: {
   
    videoSrc: "https://example.com/video.mp4", // 视频地址
    isPlaying: false, // 视频播放状态
    currentTime: 0, // 当前播放时间
    duration: 0, // 视频总时长
  },
  playVideo() {
   
    this.setData({
   
      isPlaying: true
    });
  },
  pauseVideo() {
   
    this.setData({
   
      isPlaying: false
    });
  },
  seekVideo(e) {
   
    const {
    value } = e.detail;
    const videoContext = wx.createVideoContext("videoPlayer");

    videoContext.seek(value);
  },
  updateProgress(e) {
   
    const {
    currentTime, duration } = e.detail;
    this.setData({
   
      currentTime,
      duration
    });
  },
  videoEnded() {
   
    this.setData({
   
      isPlaying: false,
      currentTime: 0
    });
  }
});
// 子组件的.js文件
Component({
   
  properties: {
   
    src: String
  },
  methods: {
   
    onPlay() {
   
      this.triggerEvent("play");
    },
    onPause() {
   
      this.triggerEvent("pause");
    },
    onSeek(e) {
   
      const {
    value } = e.detail;
      this.triggerEvent("seek", {
    value });
    },
    onTimeUpdate(e) {
   
      const {
    currentTime, duration } = e.detail;
      this.triggerEvent("timeupdate", {
    currentTime, duration });
    },
    onEnded() {
   
      this.triggerEvent("ended");
    }
  }
});
<!-- 子组件的.wxml文件 -->
<view>
  <video id="videoPlayer" src="{
    {src}}" bindplay="onPlay" bindpause="onPause" bindseeked="onSeek" bindtimeupdate="onTimeUpdate" bindended="onEnded"></video>
</view>

如上,父组件包含一个视频控制条 video-controls 和一个视频播放器区域 video-player。父组件通过属性绑定将视频地址 videoSrc 传递给子组件。

子组件是一个简单的视频播放器,当用户点击播放按钮时,触发 play 事件,父组件监听该事件并更新播放状态 isPlaying。同理,暂停按钮触发 pause 事件,父组件也进行相应的状态更新。进度条拖动时触发 seek 事件,父组件监听并进行视频进度跳转。

视频播放过程中,子组件会触发 timeupdate 事件,将当前播放时间和视频总时长传递给父组件,父组件通过监听 timeupdate 事件更新播放时间和总时长。当视频播放完成时,子组件触发 ended 事件,父组件重新设置播放状态和当前播放时间。

需要注意的是,示例中使用了微信小程序的视频组件,并通过 wx.createVideoContext 方法获取到视频上下文,从而实现视频跳转操作。

目录
相关文章
|
1月前
|
小程序 数据可视化 JavaScript
微信小程序:轻松实现时间轴组件
本文介绍了如何在微信小程序中实现一个可视化时间轴组件。该组件适用于展示用户资金流动、投资结算等时间节点,帮助用户直观了解资金去向。时间轴支持自定义节点形状、显示序号、倒序排列等功能,并通过插槽灵活定义动态内容。文中详细介绍了组件的设计与使用方法,以及如何结合动态 slot 实现自定义操作。该组件为展示用户资金信息提供了美观、易用的解决方案。
59 1
微信小程序:轻松实现时间轴组件
|
1月前
|
小程序
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
微信小程序动态tabBar实现:基于自定义组件,灵活支持不同用户角色与超过5个tab自由组合(更新版)
401 1
|
1月前
|
小程序 搜索推荐 API
微信小程序:自定义关注公众号组件样式
尽管关注公众号组件的样式固定且不可修改,但产品经理的需求却需要个性化的定制。在这种情况下,我们需要寻找解决方案,以满足这些特殊需求,尽管这可能有点棘手。
60 0
微信小程序:自定义关注公众号组件样式
|
1月前
|
小程序 前端开发 JavaScript
微信小程序图表制作利器:ECharts组件的使用与技巧
微信小程序图表制作利器:ECharts组件的使用与技巧
55 1
|
1月前
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
189 1
|
1月前
|
小程序 JavaScript
微信小程序之input组件及其获取用户输入信息
微信小程序之input组件及其获取用户输入信息
54 1
|
2月前
|
小程序 容器
微信小程序常用组件的简单使用 view,scroll-view,swiper,swiper-item,text,rich-text,button,image
本文介绍了微信小程序中常用组件的使用方法,包括view、scroll-view、swiper与swiper-item、text与rich-text、button以及image组件。详细解释了各组件的功能、属性以及如何在小程序页面中进行使用。
微信小程序常用组件的简单使用 view,scroll-view,swiper,swiper-item,text,rich-text,button,image
|
3月前
|
JSON 小程序 前端开发
终于搞懂了!微信小程序的渲染机制及组件使用
【8月更文挑战第8天】微信小程序的渲染机制及组件使用
144 3
终于搞懂了!微信小程序的渲染机制及组件使用
|
3月前
|
小程序 前端开发 API
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
100 1
|
3月前
|
小程序

热门文章

最新文章