微信小程序---组件化开发

文章目录

  • 组件化开发
    • 1.创建一个自定义组件
    • 2.自定义组件的使用
    • 3.强调:
    • 4.使用自定义组件时的细节和注意事项:
    • 5.组件的样式细节
    • 6.组件和页面通信---给组建中传递数据和样式
      • 6.1向页面中传入数据:
      • 6.2向页面传递样式
      • 6.3组件向外传递事件-自定义事件
      • 6.4页面直接调用组件修改数据/方法
    • 7.slot 插槽的使用
      • 在组件中使用多个插槽
    • 8.Component构造器

组件化开发

1.创建一个自定义组件

类似于页面,自定义组件由json,wxml,wxss,js四个文件
在wxml文件中编写属于组件自己的模板
在wxss中编写属于组件的相关样式
在js文件中定义数据结构和相关逻辑

2.自定义组件的使用

以home页面为例:
1.先在home.json中进行注册

"usingComponents": {
    "my-cpn" : "/components/my-cpn/my-cpn"
  }
  //注册形式: 标签名:组件的路径
  //路径可以是相对路径,也可以是绝对路径

2.在home.wxml文件中使用注册的标签名进行使用



<my-cpn>my-cpn>
<my-cpn/>

3.强调:

自定义组件中json文件的内容不能随意修改,只有,component为true,这个组件才是自定义组件

{
  "component": true,
  "usingComponents": {}
}

4.使用自定义组件时的细节和注意事项:

  • 自定义组件的标签名只能包含小写字母、中划线、下划线和数字
  • 自定义组件的内部可以引用其他自定义组件,在自定义组件的json文件中 "usingComponents": {}
    进行类似的注册就可以进行使用
  • 自定义组件和页面所在项目根目录名不能以 **“wx-”**为前缀,否则会报错
  • 注册全局组件,在app.json文件中定义"usingComponents"字段,然后将自定义组件进行注册,则该组件可以在全局使用

5.组件的样式细节

(1)组件内样式对外部影响

  • 组件内的class样式,只对组件wxml内的节点生效,对于引用组件的page页面不生效
  • 组件内不能使用id选择器、属性选择器、标签选择器

(2)外部样式对组件内样式的影响

  • 外部使用的class样式,只对外部wxml的class生效,对组件内是不生效的
  • 外部使用了id选择器、属性选择器不会对组建内部产生影响
  • 外部使用了标签选择器,会对组件内部产生影响

(3)结论

  • 组件内的class样式和组件外的class样式,默认有一个隔离效果;
  • 为了防止错乱,官方不推荐自定义组件使用id、属性、标签选择器,使用类选择器

(4) 如何让class可以相互影响
在组件的js文件中的Component对象中传入options属性,改变该属性中styleIsolation的对应取值
三个取值:

  • isolated 表示启用隔离样式
  • apply-shared 表示wxss样式将影响到自定义组件,但自定义组件样式不会影响页面的样式
  • shared 表示两者相互影响
 //默认isolated,隔离的
 options: {
    styleIsolation: 'isolated'
  }
 

6.组件和页面通信—给组建中传递数据和样式

页面向组件中传入:数据(properties)、样式(externalClass)、标签(slot);
组件向页面传入自定义事件

6.1向页面中传入数据:

第一种方式的步骤:

  • 不能将要显示的内容写死;
<view class="title">{{title}}view>
  • 在组件的js文件中有properties属性,这个属性是专门定义组件属性列表,在这个属性中可以定义组件要接收的数据,并对这个数据的内容进行定义;
 properties: {
    title: String,
    
  },

  • 在使用组件时传入数据
<my-prop title="哈哈哈"/>
<my-prop title="呵呵呵"/>
<my-prop title="嘿嘿嘿"/>

第一种方式的缺点:没有默认值,页面当不传值时,将不会显示
优化:在定义属性时写成对象形式

title: {
      type: String,
      value: '我是默认的标题',  //默认值
      observer: function(newval, oldval){
        console.log(newval, oldval);
        //observer 用来监听值的改变,传递一个函数
      }
    }

6.2向页面传递样式

步骤:
(1)在需要页面传递样式的地方添加类名(组件wxml文件)

<view class="title titleclass">{{title}}view>

(2)在js文件的 externalClasses 属性中的列表中添加该类名,此时将该类名传递给了调用该组件的页面;

externalClasses: ['titleclass']

(3)在使用该组件时将传递过来的类名重新赋值一个类名

<my-prop title="哈哈哈" titleclass="red"/>
<my-prop title="呵呵呵"  titleclass="green"/>
<my-prop title="嘿嘿嘿" titleclass="blue"/>

(4)使用新的类名可以在页面的wxss文件中单独给组件定义样式

  .red {
  color: red;
}

.green {
  color: green;
}

.blue {
  color: blue;
}

6.3组件向外传递事件-自定义事件

步骤:
(1) 在wxml中定义该事件名
(2) 在js文件中定义该事件的函数,并使用函数将该事件传递出去

methods: {
    handleIncrement(){
      // console.log('---------------------');
      this.triggerEvent('increment', {name: 'why', age: 18}, {})
      //increment为传递出去的事件名称, 第二个参数是一些其他数据,在event事件中可以去个这些其他数据
    }
  }

(3)在使用组件的页面进行监听,然后重新定义事件

<view>当前计数Counter: {{counter}}view>
<my-event bind:increment="handleIncrement"/>
 handleIncrement(event){
   console.log('---', event);
   
   this.setData({
     counter: this.data.counter + 1
   })
 },

6.4页面直接调用组件修改数据/方法

在组件的js文件中向外暴露一个方法

methods: {
    incrementCounter(num){
      this.setData({
        counter: this.data.counter + num
      })
    }
  }

通过id或者类名获取当前组件对象,然后后根据组件的方法对组件内的数据进行修改

const my_select = this.selectComponent('#select-id')
    my_select.incrementCounter(1)

7.slot 插槽的使用

使用插槽的目的:使组件更具扩展性

在组件中使用多个插槽

使用步骤及注意事项:

  • 使用多个插槽时,需要给每个插槽增加name属性(具名插槽)
//组件的wxml
<view>我是mslot组件的开始view>
<view class="slot1"><slot name="slot1"/>view>
<view class="slot2"><slot  name="slot2"/>view>
<view class="slot3"><slot  name="slot3"/>view>
<view>我是mslot组件的结尾view>
  • 必须在Component对象中添加一个选项:options->multipleSlots: true
options: {
    multipleSlots: true
  }
  • 根据插槽的name进行使用
<my-mslot>
  <button slot="slot2">按钮button>
  <slider slot="slot1">slider>
  <text slot="slot3">哈哈哈text>
my-mslot>

8.Component构造器

Component中可以写那些东西,具体有什么作用

// components/my-cpn/my-cpn.js
Component({
  /**
   * 组件的属性列表
   */
  //让使用者可以传入数据
  properties: {
    title: {
      type: String,
      value: ''
    }
  },

  /**
   * 组件的初始数据
   */
  //定义组件内部的初始化数据
  data: {
    counter:0
  },

  /**
   * 组件的方法列表
   */
  //用于定义组件内部的函数
  methods: {
    foo(){}
  },

 //用于定义组件的配置选项
 //multipleSlots: 使用多插槽时设置为true
//  styleIsolation: 设置样式的隔离方式 
  options: {
    
  },

  //外界给组件传入额外的样式
  externalClasses:[类名1,类名2],

  //可以监听属性的改变
  observers: {
    //监听counter属性
    counter: function(newval){
      //counter值改变时,会将最新的值传过来,但是不会传递旧值
      conslole.log(newval)
    }
  },

  //---------------组件中监听生命周期函数----------
  //1.监听所在页面的生命周期   
  pageLifetimes: {
    show(){
      conslole.log('监听组件所在页面是否显示出来了')
    },
   hide(){
     conslole.log('监听组件所在页面隐藏起来时')
   },
   resize(){
     conslole.log('监听组件所在页面尺寸改变')
   }
  },
  //2.监听组件本身的生命周期
  lifetimes: {
    created(){
      conslole.log('组件被创建出来时')
    },
    attached(){
      conslole.log('组件被添加到页面或者其他组件')
    },
    ready(){
      conslole.log('组件被渲染出来')
    },
    moved(){
      conslole.log('组件被移动到另一个节点')
    },
    detached(){
      conslole.log('组件被移除掉')
    }
  }
})

你可能感兴趣的:(微信小程序)