小程序组件
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生命周期之后
},