diff --git a/types/weixin-app/index.d.ts b/types/weixin-app/index.d.ts index d6f3965b41..ed76a02b21 100644 --- a/types/weixin-app/index.d.ts +++ b/types/weixin-app/index.d.ts @@ -2376,7 +2376,7 @@ declare namespace wx { * (初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点 * @version 1.6.0 */ - in(component: Component): SelectorQuery; + in(component: Component): SelectorQuery; /** * 在当前页面下选择第一个匹配选择器selector的节点,返回一个NodesRef对象实例,可以用于获取节点信息。 * selector类似于CSS的选择器,但仅支持下列语法。 @@ -3313,49 +3313,60 @@ declare function App(app: T & ThisType): void; declare function getApp(): App; // #endregion // #region Compontent组件 + type DefaultData = object | ((this: V) => object); -type DefaultProps = Record; + +type DefaultProps = object | Record; + type ExtendedComponent< - Instance extends Component, + Instance extends Component, Data, Methods, Options, Props -> = CombinedInstance & Component; +> = CombinedInstance & + Component; + +// CombinedInstance models the `this`, i.e. instance type for (user defined) component type CombinedInstance< - Instance extends Component, + Instance extends Component, Data, Methods, Options, Props -> = Data & Methods & Options & Props & Instance; +> = Methods & Options & Instance; + type Prop = (() => T) | { new (...args: any[]): T & object }; + type PropValidator = PropOptions | Prop | Array>; + interface DefaultMethods { [key: string]: (this: V, ...args: any[]) => any; } + interface PropOptions { type?: Prop | Array>; value?: T | null | (() => object); - observer?(value: T, old: T): void; + // bug : 对于 type 为 Object 或 Array 的属性,如果通过该组件自身的 this.setData + // 来改变属性值的一个子字段,则依旧会触发属性 observer ,且 observer 接收到的 newVal 是变化的那个子字段的值, + // oldVal 为空, changedPath 包含子字段的字段名相关信息。 + observer?(value: T, old: T, changedPath: string): void; } + type RecordPropsDefinition = { [K in keyof T]: PropValidator }; + type ArrayPropsDefinition = Array; + type PropsDefinition = ArrayPropsDefinition | RecordPropsDefinition; + type ThisTypedComponentOptionsWithRecordProps< - V extends Component, + V extends Component, Data, Methods, Options, Props > = object & - ComponentOptions< - V, - Data | ((this: Readonly & V) => Data), - Methods, - Options, - PropsDefinition - > & + ComponentOptions Data), Methods, Options, Props> & ThisType>>; interface ComponentRelation { @@ -3374,7 +3385,7 @@ interface ComponentRelation { * Component组件参数 */ interface ComponentOptions< - Instance extends Component, + Instance extends Component, Data = DefaultData, Methods = DefaultMethods, Options = object, @@ -3404,7 +3415,7 @@ interface ComponentOptions< * 类似于mixins和traits的组件间代码复用机制 * 参见 [behaviors](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/custom-component/behaviors.html) */ - behaviors?: Array<(ComponentOptions>) | string>; + behaviors?: Array<(ComponentOptions>) | string>; /** * 组件生命周期函数,在组件实例进入页面节点树时执行 * 注意此时不能调用 setData @@ -3439,7 +3450,7 @@ interface ComponentOptions< /** * Component实例方法 */ -interface Component { +interface Component { /** * 组件的文件路径 */ @@ -3455,7 +3466,12 @@ interface Component { /** * 组件数据,包括内部数据和属性值 */ - data: T; + data: D & P; + + /** + * 组件数据,包括内部数据和属性值(与 data 一致) + */ + properties: D & P; /** * 将数据从逻辑层发送到视图层,同时改变对应的 this.data 的值 * 1. 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。 @@ -3466,7 +3482,7 @@ interface Component { */ setData( data: { - [key in keyof T]?: + [key in keyof D]?: | string | number | boolean @@ -3503,19 +3519,25 @@ interface Component { * 使用选择器选择组件实例节点 * 返回匹配到的第一个组件实例对象 */ - selectComponent(selector: string): Component; + selectComponent(selector: string): Component; /** * selector 使用选择器选择组件实例节点,返回匹配到的全部组件实例对象组成的数组 */ - selectAllComponents(selector: string): Array>; + selectAllComponents(selector: string): Array>; /** * 获取所有这个关系对应的所有关联节点,参见 [组件间关系](https://mp.weixin.qq.com/debug/wxadoc/dev/framework/custom-component/relations.html) */ getRelationNodes(relationKey: string): ComponentRelation[]; } declare function Component( - options?: ThisTypedComponentOptionsWithRecordProps, D, M, O, P> -): ExtendedComponent, D, M, O, P>; + options?: ThisTypedComponentOptionsWithRecordProps< + Component, + D, + M, + O, + P + > +): ExtendedComponent, D, M, O, P>; /** * behaviors 是用于组件间代码共享的特性 * 类似于一些编程语言中的“mixins”或“traits” @@ -3525,8 +3547,14 @@ declare function Component( * behavior 也可以引用其他 behavior */ declare function Behavior( - options?: ThisTypedComponentOptionsWithRecordProps, D, M, O, P> -): ExtendedComponent, D, M, O, P>; + options?: ThisTypedComponentOptionsWithRecordProps< + Component, + D, + M, + O, + P + > +): ExtendedComponent, D, M, O, P>; // #endregion // #region Page interface PageShareAppMessageOptions { diff --git a/types/weixin-app/weixin-app-tests.ts b/types/weixin-app/weixin-app-tests.ts index 768c8da3d3..1532274ca4 100644 --- a/types/weixin-app/weixin-app-tests.ts +++ b/types/weixin-app/weixin-app-tests.ts @@ -21,7 +21,7 @@ let behavior = Behavior({ attached() {}, methods: { myBehaviorMethod() { - this.myBehaviorData; + this.properties.myBehaviorData; } } }); @@ -34,7 +34,12 @@ Component({ // 属性名 type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) value: "", // 属性初始值(可选),如果未指定则会根据类型选择一个 - observer(newVal: string, oldVal: string) {} // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange' + observer(newVal: string, oldVal: string, changedPath: string) { + const anotherKey = newVal + changedPath; + this.setData({ + anotherKey + }); + } // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange' }, myProperty2: String // 简化的定义方式 }, @@ -50,6 +55,16 @@ Component({ moved() {}, detached() {}, methods: { + readMyDataAndMyProps() { + this.data.myProperty; + this.data.myProperty2; + this.data.key; + this.data.anotherKey; + this.properties.myProperty; + this.properties.myProperty2; + this.properties.key; + this.properties.anotherKey; + }, onMyButtonTap() { // 更新属性和数据的方法与更新页面数据的方法类似 this.setData({