提交 25a29c3c 编写于 作者: 辛宝Otto's avatar 辛宝Otto 🥊

wip: 补充 uts 组件 props 通信测试

上级 292882e9
<template> <template>
<view> <view>
<call-easy-method-uni-modules ref="callEasyMethod1" :list="propsList" <call-easy-method-uni-modules ref="callEasyMethod1"></call-easy-method-uni-modules>
@propsChanged="onPropsChanged"></call-easy-method-uni-modules> <view>---</view>
<test-props :numList="numList" :objList='objList' @buttonclick='onButtonClick' @numListChange='numListChange'
@objListChange='objListChange' style="width: 80px;height: 30px;background-color: lightblue"></test-props>
<view style="flex-direction: row ;">
<text>isNumListValid: </text>
<text id='isNumListValid'>{{isNumListValid}}</text>
</view>
<view style="flex-direction: row ;">
<text>isObjListValid: </text>
<text id='isObjListValid'>{{isObjListValid}}</text>
</view>
</view> </view>
</template> </template>
...@@ -22,6 +32,12 @@ ...@@ -22,6 +32,12 @@
const changeTimes = ref(0) const changeTimes = ref(0)
const propsList = ref<number[]>([]) const propsList = ref<number[]>([])
const numList = ref<number[]>([1]) // 传递 props
const objList = ref<Array<{ id : string }>>([])
const isNumListValid = ref(false)
const isObjListValid = ref(false)
const callMethod1 = () => { const callMethod1 = () => {
// 调用组件的 foo1 方法 // 调用组件的 foo1 方法
callEasyMethod1.value?.foo1?.() callEasyMethod1.value?.foo1?.()
...@@ -53,11 +69,15 @@ ...@@ -53,11 +69,15 @@
return testInOtherFile(callEasyMethod1.value!, text) return testInOtherFile(callEasyMethod1.value!, text)
} }
const onPropsChanged = (val : number[]) => { const numListChange = (res : any) => {
changeTimes.value = changeTimes.value + 1 isNumListValid.value = res.detail as boolean
isWatched.value = isReactive(val) || isProxy(val) || isRef(val) }
console.log(55, isReactive(val), isProxy(val), isRef(val)) const objListChange = (res : any) => {
isObjListValid.value = res.detail as boolean
} }
const onButtonClick = () => {
}
const call = async () : Promise<void> => { const call = async () : Promise<void> => {
callMethod1() callMethod1()
...@@ -70,8 +90,9 @@ ...@@ -70,8 +90,9 @@
await delay() await delay()
callMethod5() callMethod5()
await delay() await delay()
// 改变 props 观察 props 返回值为非响应式值 // 改变 props: 观察 props 返回值为非响应式值
propsList.value = [3, 2, 1] numList.value = [3, 2, 1]
objList.value = [{ id: '3' }, { id: '4' }]
} }
onReady(() => { onReady(() => {
...@@ -80,6 +101,8 @@ ...@@ -80,6 +101,8 @@
defineExpose({ defineExpose({
callMethodTest, callMethodTest,
callMethodInOtherFile callMethodInOtherFile,
isNumListValid,
isObjListValid
}) })
</script> </script>
<template> <template>
<view> <view>
<call-easy-method-uni-modules ref="callEasyMethod1" :list="propsList" <call-easy-method-uni-modules ref="callEasyMethod1"></call-easy-method-uni-modules>
@propsChanged="onPropsChanged"></call-easy-method-uni-modules> <view>---</view>
<test-props :numList="numList" :objList='objList' @buttonclick='onButtonClick' @numListChange='numListChange'
@objListChange='objListChange' style="width: 80px;height: 30px;background-color: lightblue"></test-props>
<view style="flex-direction: row ;">
<text>isNumListValid: </text>
<text id='isNumListValid'>{{isNumListValid}}</text>
</view>
<view style="flex-direction: row ;">
<text>isObjListValid: </text>
<text id='isObjListValid'>{{isObjListValid}}</text>
</view>
</view> </view>
</template> </template>
...@@ -22,7 +32,10 @@ ...@@ -22,7 +32,10 @@
callEasyMethod1: null as CallEasyMethodUniModulesComponentPublicInstance | null, callEasyMethod1: null as CallEasyMethodUniModulesComponentPublicInstance | null,
isWatched: false, isWatched: false,
changeTimes: 0, changeTimes: 0,
propsList: [] as number[] numList: [1] as number[], // 传递 props
objList: [] as Array<{ id : string }>,
isNumListValid: false,
isObjListValid: false
} }
}, },
onReady() { onReady() {
...@@ -43,8 +56,9 @@ ...@@ -43,8 +56,9 @@
await delay() await delay()
this.callMethod5() this.callMethod5()
await delay() await delay()
// 改变 props 观察 props 返回值为非响应式值 // 改变 props: 观察 props 返回值为非响应式值
this.propsList = [3, 2, 1] this.numList = [3, 2, 1]
this.objList = [{ id: '3' }, { id: '4' }]
}, },
callMethod1() { callMethod1() {
// 调用组件的 foo1 方法 // 调用组件的 foo1 方法
...@@ -76,12 +90,14 @@ ...@@ -76,12 +90,14 @@
callMethodInOtherFile(text : string) : string { callMethodInOtherFile(text : string) : string {
return testInOtherFile(this.callEasyMethod1!, text) return testInOtherFile(this.callEasyMethod1!, text)
}, },
onPropsChanged(val : number[]) {
this.changeTimes = this.changeTimes + 1 numListChange(res) {
this.isNumListValid = res.detail
this.isWatched = isReactive(val) || isProxy(val) || isRef(val) },
console.log(55, isReactive(val), isProxy(val), isRef(val)) objListChange(res) {
this.isObjListValid = res.detail
},
onButtonClick() {
} }
} }
} }
......
...@@ -5,10 +5,7 @@ ...@@ -5,10 +5,7 @@
<script> <script>
export default { export default {
props: { props: {
list: {
type: Array as PropType < number[] > ,
default: () => [] as number[]
}
}, },
data() { data() {
return { return {
...@@ -17,13 +14,7 @@ ...@@ -17,13 +14,7 @@
}, },
emits:['propsChanged'], emits:['propsChanged'],
watch: { watch: {
list: {
handler(newVal, oldVal) {
console.log('isProxy',isProxy(newVal),'isReactive',isReactive(newVal),'isRef',isRef(newVal))
this.$emit('propsChanged', newVal)
},
immediate: true
}
}, },
methods: { methods: {
foo1() { foo1() {
......
{
"id": "test-props",
"displayName": "test-props",
"version": "1.0.0",
"description": "test-props",
"keywords": [
"test-props"
],
"repository": "",
"engines": {
"HBuilderX": "^3.7.0"
},
"dcloudext": {
"type": "component-uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u",
"alipay": "u"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-android": "u",
"app-ios": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
\ No newline at end of file
# test-props
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
<template>
<view>
</view>
</template>
<script lang="uts">
/**
* 引用 Android 系统库
* [可选实现,按需引入]
*/
import TextUtils from 'android.text.TextUtils';
import Button from 'android.widget.Button';
import View from 'android.view.View';
/**
* 引入三方库
* [可选实现,按需引入]
*
* 在 Android 平台引入三方库有以下两种方式:
* 1、[推荐] 通过 仓储 方式引入,将 三方库的依赖信息 配置到 config.json 文件下的 dependencies 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#dependencies)
* 2、直接引入,将 三方库的aar或jar文件 放到libs目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#android%E5%B9%B3%E5%8F%B0%E5%8E%9F%E7%94%9F%E9%85%8D%E7%BD%AE)
*
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import
* import { LottieAnimationView } from 'com.airbnb.lottie.LottieAnimationView'
*/
/**
* UTSAndroid 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsandroid.html#utsandroid)
*/
//原生提供以下属性或方法的实现
export default {
/**
* 组件名称,也就是开发者使用的标签
*/
name: "uts-button",
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
emits: ['buttonclick'],
/**
* 属性声明,组件的使用者会传递这些属性值到组件
*/
props: {
"buttontext": {
type: String,
default: "点击触发"
}
},
/**
* 组件内部变量声明
*/
data() {
return {}
},
/**
* 属性变化监听器实现
*/
watch: {
"buttontext": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : string, oldValue : string) {
if (!TextUtils.isEmpty(newValue) && newValue != oldValue) {
this.$el?.setText(newValue);
}
},
immediate: false // 创建时是否通过此方法更新属性,默认值为false
},
},
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
expose: ['doSomething'],
methods: {
/**
* 对外公开的组件方法
*
* uni-app中调用示例:
* this.$refs["组件ref"].doSomething("uts-button");
*
* uni-app x中调用示例:
* 1、引入对应Element
* import { UtsButtonElement(组件名称以upper camel case方式命名 + Element) } from 'uts.sdk.modules.utsComponent(组件目录名称以lower camel case方式命名)';
* 2、(this.$refs["组件ref"] as UtsButtonElement).doSomething("uts-button");
* 或 (uni.getElementById("组件id") as UtsButtonElement).doSomething("uts-button");
*/
doSomething(param : string) {
console.log(param);
},
/**
* 内部使用的组件方法
*/
privateMethod() {
}
},
/**
* [可选实现] 组件被创建,组件第一个生命周期,
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
*/
created() {
},
/**
* [可选实现] 对应平台的view载体即将被创建,对应前端beforeMount
*/
NVBeforeLoad() {
},
/**
* [必须实现] 创建原生View,必须定义返回值类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* (Android需要明确知道View类型,需特殊校验)
*/
NVLoad() : Button {
let button = new Button($androidContext!);
button.setText("点击触发");
button.setOnClickListener(new ButtonClickListener(this));
return button;
},
/**
* [可选实现] 原生View已创建
*/
NVLoaded() {
},
/**
* [可选实现] 原生View布局完成
*/
NVLayouted() {
},
/**
* [可选实现] 原生View将释放
*/
NVBeforeUnload() {
},
/**
* [可选实现] 原生View已释放,这里可以做释放View之后的操作
*/
NVUnloaded() {
},
/**
* [可选实现] 组件销毁
*/
unmounted() {
},
/**
* [可选实现] 自定组件布局尺寸,用于告诉排版系统,组件自身需要的宽高
* 一般情况下,组件的宽高应该是由终端系统的排版引擎决定,组件开发者不需要实现此函数
* 但是部分场景下,组件开发者需要自己维护宽高,则需要开发者重写此函数
*/
NVMeasure(size : UTSSize) : UTSSize {
// size.width = 300.0.toFloat();
// size.height = 200.0.toFloat();
return size;
}
}
/**
* 定义按钮点击后触发回调的类
* [可选实现]
*/
class ButtonClickListener extends View.OnClickListener {
/**
* 如果需要在回调类或者代理类中对组件进行操作,比如调用组件方法,发送事件等,需要在该类中持有组件对应的原生类的对象
* 组件原生类的基类为 UTSComponent,该类是一个泛型类,需要接收一个类型变量,该类型变量就是原生组件的类型
*/
private comp : UTSComponent<Button>;
constructor(comp : UTSComponent<Button>) {
super();
this.comp = comp;
}
/**
* 按钮点击回调方法
*/
override onClick(v ?: View) {
console.log("按钮被点击");
// 发送事件
this.comp.$emit("buttonclick");
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<view class="defaultStyles">
</view>
</template>
<script lang="uts">
/**
* 引用 iOS 系统库
* [可选实现,按需引入]
*/
import {
UIButton,
UIControl
} from "UIKit"
/**
* 引入三方库
* [可选实现,按需引入]
*
* 在 iOS 平台引入三方库有以下两种方式:
* 1、通过引入三方库framework 或者.a 等方式,需要将 .framework 放到 ./Frameworks 目录下,将.a 放到 ./Libs 目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#ios-平台原生配置)
* 2、通过 cocoaPods 方式引入,将要引入的 pod 信息配置到 config.json 文件下的 dependencies-pods 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-ios-cocoapods.html)
*
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import:
* 示例:import { LottieAnimationView, LottieAnimation, LottieLoopMode } from 'Lottie'
*/
/**
* UTSiOS、UTSComponent 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsios.html)
*/
import { UTSComponent } from "DCloudUTSFoundation"
import { IObjItem } from '../interface.uts'
//原生提供以下属性或方法的实现
export default {
data() {
return {
};
},
/**
* 组件名称,也就是开发者使用的标签
*/
name: "test-props",
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
emits: ['buttonclick', 'numListChange', 'objListChange'],
/**
* 属性声明,组件的使用者会传递这些属性值到组件
*/
props: {
/**
* 字符串类型 属性:buttontext 需要设置默认值
*/
"buttontext": {
type: String,
default: "点击触发"
},
numList: {
type: Array as PropType<number[]>,
default: () => [] as number[]
},
objList: {
type: Array as PropType<IObjItem[]>,
default: () => [] as IObjItem[]
}
},
/**
* 组件内部变量声明
*/
/**
* 属性变化监听器实现
*/
watch: {
"buttontext": {
/**
* 这里监听属性变化,并进行组件内部更新
*/
handler(newValue : String, oldValue : String) {
this.$el.setTitle(newValue, for = UIControl.State.normal)
},
/**
* 创建时是否通过此方法更新属性,默认值为false
*/
immediate: false
},
numList: {
handler(newVal : number[], oldVal : number[]) {
const isNumber = (val : number) : boolean => typeof val == 'number'
const isEveryNumber = (newVal as number[]).every(isNumber)
const isRawType = Array.isArray(newVal) && isEveryNumber
let data = new Map<string, any>()
data.set("detail", isRawType)
this.$emit('numListChange', data)
},
immediate: true
},
objList: {
handler(newVal:any[], oldVal:any[]) {
const isObj = (item:any):boolean => item instanceof UTSJSONObject
const isEveryObj = (newVal as any[]).every(isObj)
const isRawType = Array.isArray(newVal) && isEveryObj
let data = new Map<string, any>()
data.set("detail", isRawType)
console.log(111,newVal,isEveryObj,isRawType)
this.$emit('objListChange', data)
},
immediate: true
}
},
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
expose: ['doSomething'],
methods: {
/**
* 对外公开的组件方法
* 在uni-app中调用组件方法,可以通过指定ref的方式,例如指定uts-button 标签的ref 为 ’button‘, 调用时使用:this.$refs["button"].doSomething('message');
*/
doSomething(paramA : string) {
// 这是组件的自定义方法
console.log(paramA, 'this is in uts-button component')
},
/**
* 内部使用的组件方法
*/
},
/**
* 组件被创建,组件第一个生命周期,
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
* [可选实现]
*/
created() {
},
/**
* 对应平台的view载体即将被创建,对应前端beforeMount
* [可选实现]
*/
NVBeforeLoad() {
},
/**
* 创建原生View,必须定义返回值类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* [必须实现]
*/
NVLoad() : UIButton {
//必须实现
buttonClickListsner = new ButtonClickListsner(this)
let button = new UIButton()
button.setTitle(this.buttontext, for = UIControl.State.normal)
// 在 swift target-action 对应的方法需要以OC的方式来调用,那么OC语言中用Selector来表示一个方法的名称(又称方法选择器),创建一个Selector可以使用 Selector("functionName") 的方式。
const method = Selector("buttonClickAction")
if (buttonClickListsner != null) {
button.addTarget(buttonClickListsner!, action = method, for = UIControl.Event.touchUpInside)
}
return button
},
/**
* 原生View已创建
* [可选实现]
*/
NVLoaded() {
/**
* 通过 this.$el 来获取原生控件。
*/
this.$el.setTitle(this.buttontext, for = UIControl.State.normal)
},
/**
* 原生View布局完成
* [可选实现]
*/
NVLayouted() {
},
/**
* 原生View将释放
* [可选实现]
*/
NVBeforeUnload() { },
/**
* 原生View已释放,这里可以做释放View之后的操作
* [可选实现]
*/
NVUnloaded() {
},
/**
* 组件销毁
* [可选实现]
*/
unmounted() { }
/**
* 更多组件开发的信息详见:https://uniapp.dcloud.net.cn/plugin/uts-component.html
*/
}
/**
* 定义按钮点击后触发回调的类
* [可选实现]
*/
class ButtonClickListsner {
/**
* 如果需要在回调类或者代理类中对组件进行操作,比如调用组件方法,发送事件等,需要在该类中持有组件对应的原生类的对象。
* 组件原生类的基类为 UTSComponent,该类是一个泛型类,需要接收一个类型变量,该类型变量就是原生组件的类型。
*/
private component : UTSComponent<UIButton>
constructor(component : UTSComponent<UIButton>) {
this.component = component
super.init()
}
/**
* 按钮点击回调方法
* 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。
* [可选实现]
*/
@objc buttonClickAction() {
console.log("按钮被点击")
// 发送事件
this.component.__$$emit("buttonclick");
}
}
/**
* 定义回调类或者代理类的实例
* [可选实现]
*/
let buttonClickListsner : ButtonClickListsner | null = null
</script>
<style>
</style>
export type IObjItem = {
id : string
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册