原生小程序开发-组件、组件通讯

43 阅读8分钟

一、组件(内置基础组件、自定义组件、第三方组件库)

1. 基础组件即官方组件库,可以直接拿来用(developers.weixin.qq.com/miniprogram…

例:

view视图容器,类似div标签

scroll-view可滚动的视图容器,滚动列表效果

swiper轮播图容器组件,swiper-item轮播图item

text文本组件,类似span标签,不会换行,selectable属性实现长按选中文本内容效果

rich-text富文本组件,nodes属性支持把html字符串渲染为wxml结构(nodes="<h1>标题</h1>")

image图片组件,mode属性指定图片裁剪缩放模式(scaleToFill默认不保持横纵比缩放)

button按钮组件,open-type属性可以调用微信提供的各种功能(客服、转发、获取用户授权、信息等)

2. 自定义组件封装(类似于页面,自定义组件拥有自己的 wxml 模板和 wxss 样式)

1>. 创建一个components文件夹用来放置自定义组件
2>. 创建自定义组件(页面)

10.png

3>. 定义自定义组件内容

自定义组件js文件

Component({})注册组件页面,配置项:

data:{}组件内部初始数据,

properties:{}接收外面传入的数据,类似于vue中的props,

methods:{}组件方法列表,

observers:{'字段a/对象.属性a/对象.**,字段b':function(字段a新值/属性a的新值/obj,字段b新值){}}数据监听器(监听某些字段的变化,对象属性的变化,如果对象属性太多,可以用对象.**监听对象中所有属性的变化)

纯数据字段:指不用于界面渲染的data字段(既不会展示在界面上,也不会传递给其他组件),有助于提升页面更新的性能。

options:{pureDataPattern:/^_/}字段名符合这个正则表达式(以_开头)的字段将成为纯数据字段

Component({

  options: {

    pureDataPattern:/^_/,//以_开头的字段将成为纯数据字段
    
    multipleSlotstrue // 在组件定义时的选项中启用多 slot 支持

  },

  /**

   * 组件的属性列表

   * 类似于vue props,接收外面传入属性

   */

  properties: {

     // title:String,
     title:{
       type:String,
       valve:'标题'//默认值
     }

  },
 

  /**

   * 组件的初始数据

   */

  data: {

     content:'我是组件内部数据'n1:0,
     n2:0,
     sum:0,
     _a:true//纯数据字段

  },

 

  /**

   * 组件的方法列表

   */

  methods: {

     show(){

       console.log('show method >>>>',this.data.content);

     },
     addN1(){ this.setData(( n1: this.data.n1 + 1 })),
     addN2(){ this.setData({ n2: this.data.n2 + 1 })}

  },
  
  //数据监听器,同vue中的watch
  observers:{
    'n1,n2': function(newn1,newn2){//监听 n1 和 n2 数据的变化
      this.setData({sum:newn1 + newn2 })// 通过监听器,自动计算 sum 的值
    }
  }

})

自定义组件wxml文件

<view class="g-container">

   <view>自定义组件</view>

   <view>

       <view>标题: {{title}}</view>

       <view>内容: {{content}}</view>

       <button bind:tap="show" type="primary" size="mini">确定</button>

       <view>{{n1}} + {{n2}} = {{sum}}</view>
       <button bind:tap="addN1" type="primary" size="mini">n1+1</button>
       <button bind:tap="addN2" type="primary" size="mini">n2+1</button>
   </view>

</view>

 

4>.注册自定义组件

在要使用自定义组件的页面的json文件中注册自定义组件(”组件名”:”路径”)

{

  "navigationBarTitleText": "列表",
  
  "component":true,

  "usingComponents": {

     "myText":"../../components/MyText/index"

  }

}
5>.使用自定义组件

在要使用自定义组件的页面的wxml文件中直接使用传参即可

<view>

  <!-- 自定义组件 -->

  <myText title="自定义组件"></myText>

</view>

  组件与页面区别:

组件json文件需要声明"component":true,

组件js文件用Component({})注册组件页面

页面js文件用Page({})注册页面

组件js文件事件处理函数要定义到methods节点中

页面js文件事件处理函数要定义到与data平齐的节点中

组件样式特点:

  1. 隔离性:组件与组件、组件与外界页面之间样式互不影响

  2. app.wxss 中的全局样式对组件无效

  3. 只有 class 选择器会有样式隔离效果,id 选择器、属性选择器、标签选择器不受样式隔离的影响

开发过程中有时需要外界页面控制组件样式,可以通过 stylelsolation 修改组件的样式隔离选项,有两种方式:

  1. 在组件js文件中通过options修改组件的样式隔离选项
Component({

  options: {

    stylelsolation: 'isolated'//isolated启用样式隔离;apply-shared页面样式可以影响组件样式,但组件样式无法影响页面样式;shared页面组件样式互相影响

  },
})
  1. 在组件json文件中配置
{

    "stylelsolation": "isolated"

}

3. 第三方组件库

1>. WeUI:

是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计。 github下载地址 github.com/yuanqingjia…

使用:(以mp-dialog弹框组件为例)

  •  通过useExtendedLib扩展库的方式引入,这种方式引入的组件不会计入代码包大小
(1)全局配置文件app.json文件中引入weui
{

  "pages": [

    "pages/goodsList/index",

    "pages/goodsDetail/index"

  ],

  "window": {

    "backgroundTextStyle": "light",

    "navigationBarBackgroundColor": "#f00",

    "navigationBarTitleText": "小程序",

    "navigationBarTextStyle": "white"

  },

  "sitemapLocation": "sitemap.json",

  "useExtendedLib": {

    "weui": true

  }

}
(2)在要使用该组件库的页面的json配置文件中注册组件(mp-dialog弹框组件)
{

  "navigationBarTitleText": "商品列表",

  "usingComponents": {

     "myText":"../../components/MyText/index",
     
     "mp-dialog":"weui-miniprogram/dialog/dialog"

  }

}
(3)在wxml文件中使用
<view>

  <!-- weui组件库 -->

  <mp-dialog title="标题" show="{{isShow}}">

    <myText id="mytext" title="weui组件库">

      <image slot="logo" style="width: 200px;height: 200px;" src="{{src}}"></image>

      <view slot="footer">

        <view>底部区域</view>

        <text>========</text>

      </view>

    </myText>

  </mp-dialog>

  <button bind:tap="onAdd">弹框</button>

</view>
(4)js文件逻辑内容
// pages/goodsList/index.js

Page({

  /**

   * 页面的初始数据

   */

  data: {

    isShow: false,

  },

  onAdd() {

    const isShow = this.data.isShow;

    this.setData({ isShow: !isShow });

  }

});

 

  • 通过npm下载构建,包名为weui-miniprogram

 

2>.vant-weapp:(可能会有版本问题出现组件展示不出来的问题,可以用npm uninstall @vant/weapp卸载,删掉miniprogram_npm目录,然后通过npm i @vant/weapp@1.10.3 -S --production重新下载指定版本)

官网:youzan.github.io/vant-weapp/…

使用:(以van-button/van-dialog组件为例)

(1)安装

npm init -y (初始化生成package.json文件)

npm i @vant/weapp -S --production或者yarn add @vant/weapp --production(安装生成node_modules文件)

(2)修改app.json文件

将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。

(3)修改project.config.json文件

在project.config.json文件中的"packNpmRelationList":[]中添加对象(指定package.json文件的路径和小程序安装vant组件库的路径)

"packNpmRelationList": [

      {

        "packageJsonPath": "./package.json",

        "miniprogramNpmDistDir": "./"

      }

    ],
(4)点击左上角工具 -> 构建 npm,执行完以后项目根目录会增加:“miniprogram_npm”目录,就是vant- weapp的组件。构建完成后,即可引入组件。
(5)在app.json(全局)或index.json中注册组件
"usingComponents": {

     "van-button""@vant/weapp/button/index",

     "van-dialog""@vant/weapp/dialog/index",

     "van-uploader""@vant/weapp/uploader/index",

     "van-nav-bar""@vant/weapp/nav-bar/index"

  }
(6)wxml文件中使用组件
<view>

  <!-- vant-weapp组件库 -->

  <van-button type="primary" size="small" bind:tap="onDialog">主要按钮</van-button>

  <van-dialog id="van-dialog" show="{{ isDialog }}" />

  <van-uploader file-list="{{ fileList }}" bind:after-read="afterRead" />

  <van-nav-bar title="标题" left-text="返回" right-text="按钮" />

</view>
(7)js文件中逻辑代码
Page({

  /**

   * 页面的初始数据

   */

  data: {

    isDialogfalse,

    fileList: [],

  },

 

  onDialog() {

    const isDialog = this.data.isDialog;

    this.setData({ isDialog: !isDialog });

  },

  afterRead(event){

    console.log(event.detail);

  },

});

 

二、组件通讯

1. 父传子(直接传)

1>.父组件json文件中注册子组件
{

  "navigationBarTitleText": "列表",

  "usingComponents": {

     "myText":"../../components/MyText/index"

  }

}
2>. wxml文件中使用子组件,在子组件标签中定义要传的属性
<view>

  <!-- 父传子 -->

  <myText title="自定义组件"></myText>

</view>
3>.子组件js文件中通过prperties配置项接收父组件传入的属性
Component({

  options: {

    multipleSlots: true // 在组件定义时的选项中启用多 slot 支持

  },

  /**

   * 组件的属性列表

   * 类似于vue props,接收外面传入属性

   */

  properties: {

     title:''

  },

  /**

   * 组件的初始数据

   */

  data: {

     content:'我是组件内部数据'

  },

 

  /**

   * 组件的方法列表

   */

  methods: {}

})
4>. 子组件wxml文件中可直接使用
<view class="g-container">

   <view>自定义组件</view>

   <view>

       <view>标题: {{title}}</view>

       <view>内容: {{content}}</view>

   </view>

</view>

 

 

2. 子传父(父组件传递自定义事件到子组件,子组件触发自定义事件,返回数据给父组件)

1>. 父组件js文件中定义事件,接收数据
Page({

  /**

   * 页面的初始数据

   */

  data: {

message: "",

},

  bindContent(content) {

    console.log("触发自定义事件执行父组件代码", content.detail);

    const message = content.detail;

    this.setData({ message });

  }

});
2>. 父组件wxml中传递事件给子组件
<view>

  <!-- 子传父,传递自定义事件到子组件,子组件触发事件,返回数据 -->

<text>{{message}}</text>

  <myText bind:getcontent="bindContent"></myText>

</view>
3>. 子组件js文件中触发事件,返回数据给父组件(小程序中无需接收事件,直接触发即可,通过triggerEvent触发,类似于vue中emit)
Component({

  options: {

    multipleSlots: true // 在组件定义时的选项中启用多 slot 支持

  },

  /**

   * 组件的属性列表

   * 类似于vue props,接收外面传入属性

   */

  properties: {

     title:''

  },

 

  /**

   * 组件的初始数据

   */

  data: {

     content:'我是组件内部数据'

  },

  /**

   * 组件的方法列表

   */

  methods: {

     show(){

       console.log('show method >>>>',this.data.content);

      //  emit('getcontent',100)

      this.triggerEvent('getcontent',this.data.content)

     },

  }

})

3. 传内容(如图片内容)插槽与具名插槽

1>.父组件wxml文件
<view>

  <!-- 插槽 -->

  <myText>

    <image style="width: 200px;height: 200px;" src="{{src}}"></image>

  </myText>

<!-- 具名插槽 -->

  <myText>

    <image slot="logo" style="width: 200px;height: 200px;" src="{{src}}"></image>

    <view slot="footer">

      <view>底部区域</view>

      <text>========</text>

    </view>

  </myText>

</view>
2>. 子组件wxml文件
<view class="g-container">

   <view>

       <view>标题: {{title}}</view>

       <view>内容: {{content}}</view>

       <view>

          <slot></slot>

       </view>

<view>

          <slot name="logo"></slot>

          <slot name="footer"></slot>

       </view>

   </view>

</view>

 

4. 组件实例传参(小程序中可以通过this.selectComponent(“id名”)方法获取组件实例,这样就可以直接访问组件的数据和方法了。vue中可以通过ref属性拿到组件实例,从而调用组件中的数据和方法,或者通过expose方法暴露)

1>. 父组件wxml文件中给子组件加个id名
<view>

  <!-- 组件实例传参 -->

  <myText>

    <image id="mytext"

style="width: 200px;height: 200px;" src="{{src}}"></image>

  </myText>

<text>{{message}}</text>

  <button bind:tap="bindGetInstance">获取子组件实例</button>

</view>
2>. 父组件js文件中调用this.selectComponent(“id名”)方法获取子组件实例
Page({

  /**

   * 页面的初始数据

   */

  data: {},

  bindGetInstance() {

    //获取子组件实例

    const instance = this.selectComponent("#mytext");

    //调数据和方法

    console.log(instance.data.content);

    instance.show();

  }

});
3>. 子组件js文件中的数据和方法
Component({

  options: {

    multipleSlotstrue // 在组件定义时的选项中启用多 slot 支持

  },

  /**

   * 组件的属性列表

   * 类似于vue props,接收外面传入属性

   */

  properties: {

     title:''

  },

 

  /**

   * 组件的初始数据

   */

  data: {

     content:'我是组件内部数据'

  },

  /**

   * 组件的方法列表

   */

  methods: {

     show(){

       console.log('show method >>>>',this.data.content);

     },

  }

})