前端框架:小程序、vue、react

小程序组件

2019-01-18  本文已影响62人  js_hcl

1.组件定义

//json部分----------------------------------------------------
{
  "component": true,  //标明这个是组件
  "usingComponents": {} //组件也可以使用其它的组件
}
<!--wxml部分---------------------------------------------------->
1.和page类似,多了卡槽
<!--单个卡槽-->
<slot> </slot>   
<!--多卡槽-->
<slot name="before"></slot> 
<slot name="after"></slot> 

2.和vue不一样的是,它确实是自定义的标签名插入到了xml而不是组件内容的替代
->1.组件wxml定义时,不需要只有一个根节点
->2.可以为自定义标签,在组件内定义class。:host
->3.使用组件时,卡槽位置,不需要是一个根节点
/*wxss部分--------------------------------------------------------*/
因为组件的标签名及属性都是可以自定义的 ,及组件的复用性
为了避免id重复及查找速度太慢或出错
尽可能只使用class选择器

其它:
->1.页面的全局样式page{} , 组件的全局样式:host{}
//js部分-------------------------------------------------------
页面定义page 改成 组件定义component
Component({
  /*------------------------代码复用方式-------------------------------------------------*/
,
  behaviors: [],//类似于vue的mixins和traits的组件间代码复用机制

  /*------------------------定义关联-------------------------------------------------*/
,
relations:{

}

//--------------------options一些选项----------------------------------------
,
options:{
  multipleSlots: true //在组件定义时的选项中启用多slot支持
 ,addGlobalClass: true,//使组件接受全局样式,尽量避免
},

  //------------------------组件的两种对外定义属性方式------------------------------------
,
  properties: {//对外定义的接收属性
    myProperty: { // 属性名
      type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
      value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
      observer(newVal, oldVal, changedPath) { }  // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串
    },//以下为 简化的定义方式
    myProperty2: String 
  },

  externalClasses:['myclass']//作为组件的class使用。内部和外部两个类的优先级是未定义的,因此最好避免这种情况

  //--------------------组件的内部数据----------------------------------------
,
  data: {}, // 私有数据,可用于模板渲染

  //--------------------组件方法----------------------------------------
,
  methods: {//组件的方法
    method_one(){},    //普通方法
    method_two(){},
    _myPrivateMethod1() {  },  // 内部方法建议以下划线开头
    _myPrivateMethod2() {  },
},


//--------------------生命周期----------------------------------------
,

lifetimes: {       //生命周期函数,可以为函数,或一个在methods段中定义的方法名
    created(){},
    attached(){},
    ready(){},
    moved(){},
    detached(){}
  },
pageLifetimes: {    //组件所在页面的生命周期函数
    show() { },
    hide() { },
    resize() { },
  }
//--------------------组件扩展-------------
,

definitionFilter:{

}
})

2.实例(this)的属性和方法

page component 说明
is 文件的路径
id 节点id
dataset 节点dataset
data 组件数据,包括内部数据和属性值
properties 组件数据,包括内部数据和属性值(与 data 一致)
setData 设置data并执行视图层渲染
hasBehavior 检查组件是否具有 behavior (检查时会递归检查被直接或间接引入的所有behavior)
triggerEvent 触发事件,参见 组件事件
createSelectorQuery 创建一个 SelectorQuery 对象,选择器选取范围为这个组件实例内
createIntersectionObserver 创建一个 IntersectionObserver 对象,选择器选取范围为这个组件实例内
selectComponent 使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象(会被 wx://component-export 影响)
selectAllComponents 使用选择器选择组件实例节点,返回匹配到的全部组件实例对象组成的数组
getRelationNodes 获取这个关系所对应的所有关联节点,参见 组件间关系
groupSetData 立刻执行 callback ,其中的多个 setData 之间不会触发界面绘制(只有某些特殊场景中需要,如用于在不同组件同时 setData 时进行界面绘制同步)

3.生命周期(其实是view Thread)

小程序组件 vue组件 说明
beforeCreate 实例化this之前(除要操作this,同create可以加载请求)
created created 实例化this之后
attached beforeMount 虚拟树形成,可以操作视图数据(setData)
ready mounted 已挂载到DOM中,可以访问节点信息
moved 组件位置更新
beforeUpdate/updated 组件数据更新
detached beforeDesotry/destoryed 组件卸载

小程序页面生命周期(js Thread)
视图ready之后,通知js。所以页面生命周期onReady比页面渲染的ready晚
即:组件的ready先执行,在执行页面的OnReady()

2.组件使用

//使用页面的json
{
  "usingComponents": {// 页面自定义组件配置 
    "这里是组件名字(文件名字)": "这里是路径"
  }
}
<view>
  <!-- 以下是对一个自定义组件的引用 -->
  <component-tag-name inner-text="Some text">
    <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
    <view>这个是单slot的插入方式</view>
    <view>可以不用包裹在一个根节点上...</view>

    <!-- 如果开启多slot-->

     <!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
    <view slot="before">这里是插入到组件slot name="before"中的内容</view>
    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
    <view slot="after">这里是插入到组件slot name="after"中的内容</view>
  </component-tag-name>
</view>

3.组件实例

组件的实例
(4) ["__viewData__", "__data__", "__wxWebviewId__", "__wxExparserNodeId__"]

(5) ["constructor", "method_one", "method_two", "_myPrivateMethod1", "_myPrivateMethod2"]

(17) ["is", "id", "dataset", "properties", "data", "setData", "groupSetData", "replaceDataOnPath", 
"mergeDataOnPath", "applyDataUpdates", "hasBehavior", "triggerEvent", "createSelectorQuery", 
"createIntersectionObserver", "selectComponent", "selectAllComponents", "getRelationNodes"]

-------------------------------------
page的实例

(16) ["__viewData__", "__data__", "__wxWebviewId__", "__wxExparserNodeId__",
 "__route__", "route", "__displayReporter", "onLoad", "onShow", "onReady", 
"onHide", "__callPageLifeTime__", "onRouteEnd", "onUnload", "onResize", "options"]

(6) ["constructor", "onLoad", "onShow", "onReady", "onHide", "__freeData__"]

(17) ["is", "id", "dataset", "properties", "data", "setData", "groupSetData", "replaceDataOnPath", 
"mergeDataOnPath", "applyDataUpdates", "hasBehavior", "triggerEvent", "createSelectorQuery", 
"createIntersectionObserver", "selectComponent", "selectAllComponents", "getRelationNodes"]
----------------------------------------
对比下来:
page实例本身比组件多了页面生命周期属性
及route:到当前页面的路径
options:还未明确暴露
及其它私有方法

原型:
组件的原型,比page的多了在组件methods定义的方法

原型的原型:
一样:即最上面继承的是一样的
注:发现is === route

4.抽象节点

定义组件的wxml中:
<!-- selectable在这里是抽象组件名-->
<selectable ></selectable > 
定义组件的json的wxml中
//组件声明在usingComponents中
"usingComponents": {} 

//抽象组件声明在componentGenerics中
"componentGenerics": {
    "selectable": true
  }
使用该组件的页面wxml中
<!-- 自定义组件的调用者确定该抽象节点是什么-->
<my-component  generic:selectable="select1"></my-component>
使用该组件的页面的json中。
//即要声明传给抽象节点的组件
  "usingComponents": {
    "my-component": "/components/component-tag-name",
    "select1":"/components/select2",
    "select2": "/components/select2"
  }

到此为止,子组件可以获得父组件预定给的属性及方法

5.组件通信

5.1 父向子通信----数据绑定

<my-component  myProperty="xxx"></my-component>

5.2 子向父通信----事件触发

=>一、子组件触发事件
  this.triggerEvent('myevent', myEventDetail, myEventOption)
  myevent:自定义事件名
  myEventDetail:detail对象。用于传递信息。父组件捕获该事件后可以获得该对象
  myEventOption:事件选项:{bubbles:boolen, 
                          composed:boolen,
                          capturePhase:boolen
                        }
即事件是否冒泡
事件是否可以穿越组件边界:若为true,则如果该组件的父节点(`对比父组件`)如果能捕获也会触发
事件是否拥有捕获阶段

=>二、父组件捕获事件
<my-component  bind:myevent="xxx"></my-component>

5.3 其它通信方式

父组件获得子组件实例

一、微信小程序中父组件获取子组件对象方法(因为访问节点信息,在onReady中才能访问到)

1.selectComponent,返回选择器的第一个组件

2.selectAllComponents,返回选择器的组件列表

使用示例:
   //selectComponent:返回选择器的第一个组件,一般用id获取
    var showTwo = this.selectComponent('#myShow');
    //访问属性,使用data访问内部属性和组件属性
    console.info(showTwo.data);
    //执行操作
    showTwo.innerAdd();

    //selectAllComponents:返回选择器的组件列表,一般用样式获取
    var showThree = this.selectComponent('.myShow');
    console.info(showThree.data);
    showThree.innerAdd();

到此,子组件可以获得父组件预定给的(数据绑定/事件监听)属性及方法
及父组件可以访问子组件的属性及方法

建立关联relations
关联后,可以相互访问

到目前两个问题不清楚
1.子组件要在父组件的Slot中,才能关联?
  <custom-ul>
      <custom-li>item 1</custom-li>   <!-- 及父类slot卡槽的形式-->
  </custom-ul>

  如果
 在父组件custom-ul中,
<!-- 组件模板 -->
<view class="wrapper">
  <slot></slot>
  <custom-li></custom-li>  <!-- 这里触发不了关联-->
</view>
2.多组件关联时,的type不明朗及问题?

获得关联对象的方法:

this.getRelationNodes('path/to/custom-li');//path/to/custom-li为关联的组件路径


linked(target) {//或者在组件关联的关系生命周期函数中获得
        // 每次被插入到custom-ul时执行,target是custom-ul节点实例对象,触发在attached生命周期之后
      },

上一篇 下一篇

猜你喜欢

热点阅读