diff --git a/docs/plugin/uts-component-vue.md b/docs/plugin/uts-component-vue.md index 3edc4ec46cb5ef490ab5a5e703ab6f13aaaba1ed..c57417a3ac1e6e817d3e106fe85de69a2324b538 100644 --- a/docs/plugin/uts-component-vue.md +++ b/docs/plugin/uts-component-vue.md @@ -1,547 +1,548 @@ -# uts插件 - 标准模式组件开发 +# uts插件 - 标准模式组件开发 > HBuilderX4.31 及以上版本支持 - + 本文重点在于讲述如何在app-android和app-ios上,使用vue组件开发规范封装原生UI封装为 uni-app x 项目使用的UTS组件,供使用者在uvue页面template中以组件的方式调用。 -主要思路是将app平台的原生view关联内置 [native-view](../component/native-view.md) 组件,实现UTS组件的特定功能及UI展示。 - - - -## 前置条件 - -继续阅读文档前,开发者需要了解以下前置条件: - -- 了解 `标准模式` 和 `uni-app兼容模式` 的差异,详情参考[uts组件开发概述](./uts-component.md) -- 了解 [uts语法](/uts/) 和 [uts原生插件](uts-plugin.md) -- 了解 [vue组件](https://uniapp.dcloud.net.cn/tutorial/vue3-components.html) -- 了解 [native-view组件](../component/native-view.md) - - - -## UTS插件-标准模式组件目录结构@dir - -
-
-┌─components                      // vue组件代码
-|   ├─xxx                      // vue组件名称文件夹  xxx代替组件名称
-|       ├─xxx.uvue             // vue组件uts代码 xxx代替组件名称
-├─static                          // 静态资源
-├─utssdk
-│	├─app-android                 //Android平台目录
-│	│	├─assets                  //Android原生assets资源目录,可选
-│	│	├─libs                    //Android原生库目录,可选
-│	│	├─res                     //Android原生res资源目录,可选
-│	│	├─AndroidManifest.xml     //Android原生应用清单文件,可选
-│	│	├─config.json             //Android原生配置文件
-│	│	├─index.uts               //Android原生插件能力实现,可选
-│	├─app-ios                     //iOS平台目录
-│	│	├─Frameworks              //iOS原生依赖的第三方 framework 依赖库存放目录,可选
-│	│	├─Resources               //iOS原生所依赖的资源文件存放目录,可选
-│	│	├─info.plist              //iOS原生所需要添加到主 info.plist 文件中的配置文件,可选
-│	│	├─UTS.entitlements        //iOS原生所需要添加到主工程 .entitlements 文件中的配置文件,可选
-│	│	├─config.json             //iOS原生配置文件
-│	│	├─index.uts               //iOS原生插件能力实现,可选
-│	├─web                         //web平台目录
-│	│	└─index.uts
-│	└─index.uts                   // 跨平台插件能力实现,可选
-└─package.json                    // 插件清单文件
-
-
- -如上所示,UTS插件-标准模式组件目录结构与UTS插件基本相同,差别在于components目录,vue组件代码存放components目录下。 - -其他目录文件详情可参考[UTS插件文档](https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html#%E6%8F%92%E4%BB%B6%E7%9A%84%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84) +主要思路是将app平台的原生view关联内置 [native-view](../component/native-view.md) 组件,实现UTS组件的特定功能及UI展示。 + + + +## 前置条件 + +继续阅读文档前,开发者需要了解以下前置条件: + +- 了解 `标准模式` 和 `uni-app兼容模式` 的差异,详情参考[uts组件开发概述](./uts-component.md) +- 了解 [uts语法](/uts/) 和 [uts原生插件](uts-plugin.md) +- 了解 [vue组件](https://uniapp.dcloud.net.cn/tutorial/vue3-components.html) +- 了解 [native-view组件](../component/native-view.md) + + + +## UTS插件-标准模式组件目录结构@dir + +
+
+┌─components                      // vue组件代码
+|   ├─xxx                      // vue组件名称文件夹  xxx代替组件名称
+|       ├─xxx.uvue             // vue组件uts代码 xxx代替组件名称
+├─static                          // 静态资源
+├─utssdk
+│	├─app-android                 //Android平台目录
+│	│	├─assets                  //Android原生assets资源目录,可选
+│	│	├─libs                    //Android原生库目录,可选
+│	│	├─res                     //Android原生res资源目录,可选
+│	│	├─AndroidManifest.xml     //Android原生应用清单文件,可选
+│	│	├─config.json             //Android原生配置文件
+│	│	├─index.uts               //Android原生插件能力实现,可选
+│	├─app-ios                     //iOS平台目录
+│	│	├─Frameworks              //iOS原生依赖的第三方 framework 依赖库存放目录,可选
+│	│	├─Resources               //iOS原生所依赖的资源文件存放目录,可选
+│	│	├─info.plist              //iOS原生所需要添加到主 info.plist 文件中的配置文件,可选
+│	│	├─UTS.entitlements        //iOS原生所需要添加到主工程 .entitlements 文件中的配置文件,可选
+│	│	├─config.json             //iOS原生配置文件
+│	│	├─index.uts               //iOS原生插件能力实现,可选
+│	├─web                         //web平台目录
+│	│	└─index.uts
+│	└─index.uts                   // 跨平台插件能力实现,可选
+└─package.json                    // 插件清单文件
+
+
+ +如上所示,UTS插件-标准模式组件目录结构与UTS插件基本相同,差别在于components目录,vue组件代码存放components目录下。 + +其他目录文件详情可参考[UTS插件文档](https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html#%E6%8F%92%E4%BB%B6%E7%9A%84%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84) 也就是说:**在components/xxx/xxx.uvue这个uvue组件文件中,定义组件的属性、事件、方法;然后这些属性、方法的具体实现,则调用在utssdk下的uts插件实现。** - -## 开发UTS插件-标准模式组件 - -下面我们以一个例子来讲解标准模式组件的开发。 - -我们开发一个`native-button`组件,目标是把Android和iOS的原生button封装成uvue组件。 - -Android的原生button会带有水波纹效果。uni-app自带的button组件并没有这个效果。 - -该组件计划提供一个 text属性,用于显示按钮的文字;有一个buttonTap事件用于处理点击。 - -let's go! - -### 新建标准模式组件 - -HBuilder X 选中你的项目,项目根目录选中`uni_modules`目录,右键选择新建`uni_modules`插件,弹窗后分类选择 “UTS插件-标准模式组件”,填写组件名称,以下均以 `native-button` 为例 - -![](https://web-ext-storage.dcloud.net.cn/doc/uts/uts_plugin/create-uts-vue-component.png) - -创建完毕 HBuilder X 会自动创建一批模版文件,参考:[前述目录结构](#dir) - -### 标准模式组件功能实现 - -#### 添加 native-view - -上一步创建标准模式组件(名称为native-button)后,HBuilder X 会自动创建components/native-button/native-button.uvue文件。 - -这个文件是一个标准的uvue组件,符合easycom规范,在这个文件编写组件的属性、事件。 - -首先在该文件的template区添加 [native-view 组件](../component/native-view.md) - -```html - -``` - -#### native-view 与 原生对象关联 - -native-view 组件的用途就是提供一个占位view,并且可以和原生的view进行绑定。 - -native-view 组件初始化会触发 @init 事件,如下代码在init时创建原生NativeButton对象,在其内部实现了view的绑定。 - -[NativeButton](#utscode)是在utssdk目录的app-android和app-ios目录下的index.uts中定义的原生对象。NativeButton对象内部处理原生view与native-view绑定关联业务。 - -native-button.uvue代码中用NativeButton对象调用插件相关的API。 - -native-view 组件在uts中对应着UniNativeViewElement对象,将 UniNativeViewElement 传递给NativeButton对象,进行关联绑定。 - - -::: preview - -> 组合式 API - -```html - - -``` - -> 选项式 API - -```html - - -``` - -::: - -#### 组件声明方法 - -vue中,为组件定义方法很简单,但分选项式和组合式。 - -选项式中,在 methods 节点中添加updateText方法;组合式中,直接定义function updateText。参考vue文档[页面调用vue组件方法](https://doc.dcloud.net.cn/uni-app-x/vue/component.html#page-call-component-method) - -native-button组件使用者可调用该updateText方法中更新native-button文字。 - -但在vue组件的updateText方法中,需再次调用NativeButton的updateText方法,在原生插件中实现按钮文字更新。 - -::: preview - -> 组合式 API - -```ts - -``` - -> 选项式 API - -```ts -methods: { - //对外函数 - updateText(value: string) { - this.button?.updateText(value) - } -} -``` - -::: - -#### 组件声明属性props - -native-button 声明组件属性props,例如native-button的文案信息text属性,按vue组件规范监听到text属性更新,通过NativeButton对象驱动更新原生view属性,在components/native-button/native-button.uvue编写如下代码,具体参考vue文档[vue组件Props规范](https://cn.vuejs.org/guide/typescript/composition-api#typing-component-props) - -::: preview - -> 组合式 API - -```html - -``` - -> 选项式 API - -```html - -``` - -::: - -#### 组件声明事件 - -native-button 声明事件,例如原生组件触发点击事件@buttonTap, NativeButton对象通过 UniNativeViewElement 的 dispatchEvent 函数触发native-view的 @customClick 自定义事件。native-button.uvue监听native-view的 @customClick 自定义事件实现emit触发声明事件,具体参考[vue组件事件规范](https://cn.vuejs.org/guide/typescript/composition-api#typing-component-emits) - -::: preview - -> 组合式 API - -```html - - -``` - -> 选项式 API - -```html - - -``` - -::: - -**注意:** - -目前自定义事件参数仅支持[UniNativeViewEvent](../component/native-view#uninativeviewevent) - -native-button/components/native-button/native-button.uvue 最终代码如下: - -::: preview - -> 组合式 API - -``` html - - -``` - -> 选项式 API - -```html - - -``` - -::: - -#### 实现NativeButton对象@utscode - -utssdk目录实现不同平台的原生NativeButton对象,构造参数获取UniNativeViewElement对象与原生view绑定,封装原生view功能关联的API。 - -::: preview - -> Android - -```uts -import { Button } from "android.widget" - -export class NativeButton { - $element : UniNativeViewElement; - - constructor(element : UniNativeViewElement) { - //接收传递过来的UniNativeViewElement - this.$element = element; - this.bindView(); - } - - button : Button | null = null; - bindView() { - //通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文 - this.button = new Button(this.$element.getAndroidActivity()!); //构建原生view - //限制原生Button 文案描述不自动大写 - this.button?.setAllCaps(false) - //监听原生Button点击事件 - this.button?.setOnClickListener(_ => { - const detail = {} - //构建自定义UniNativeViewEvent返回对象 - const event = new UniNativeViewEvent("customClick", detail) - //触发原生Button的点击事件 - this.$element.dispatchEvent(event) - }) - //UniNativeViewEvent 绑定 安卓原生view - this.$element.bindAndroidView(this.button!); - } - - updateText(text: string) { - //更新原生Button 文案描述 - this.button?.setText(text) - } - - destroy(){ - //数据回收 - } -} -``` - -> iOS - -```uts -import { UIButton, UIControl } from "UIKit" - -export class NativeButton { - - element : UniNativeViewElement; - button : UIButton | null; - - constructor(element : UniNativeViewElement) { - // 接收组件传递过来的UniNativeViewElement - this.element = element; - super.init() - this.bindView(); - } - - // element 绑定原生view - bindView() { - // 初始化原生 UIButton - this.button = new UIButton(type=UIButton.ButtonType.system) - // 构建方法选择器 - const method = Selector("buttonClickAction") - // button 绑定点击回调方法 - button?.addTarget(this, action = method, for = UIControl.Event.touchUpInside) - // UniNativeViewElement 绑定原生 view - this.element.bindIOSView(this.button!); - } - - updateText(text : string) { - // 更新 button 显示文字 - this.button?.setTitle(text, for = UIControl.State.normal) - } - - /** - * 按钮点击回调方法 - * 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。 - */ - @objc buttonClickAction() { - //构建自定义 UniNativeViewEvent 对象 - let event = new UniNativeViewEvent("customClick") - //触发自定义事件 - this.element.dispatchEvent(event) - } - - destroy() { - // 释放 UTS 实例对象,避免内存泄露 - UTSiOS.destroyInstance(this) - } -} -``` - -::: - -更多实现可参考 标准模式组件 [native-button](https://gitcode.net/dcloud/hello-uni-app-x/-/tree/dev/uni_modules/native-button) - -此时一个简单的UTS插件-标准模式组件就完成了, - -**注意:** -+ UTS插件-标准模式组件的 components 目录下的代码中不应该含有原生平台任何引用对象,这会导致vue原生组件无法跨平台,推荐与原生平台关联的代码都放在utssdk中 -+ ios平台需要vue组件主动释放 uts 实例,所以页面触发 unmounted 生命周期时需要调用 this.button?.destroy() 避免内存泄露 -+ android平台 native-view 组件不支持border、background、box-shadow属性,可以使用view标签包裹native-view,在view标签设置以上属性 - - -### 页面引用UTS插件-标准模式组件@pagecode - -以 native-button 为例, 创建标准模式组件的项目页面可以直接使用 native-button 标签,也可将native-button插件包放置其他项目的uni-modules文件夹中。项目页面即可使用 native-button 标签 - -```html - - - - - -``` - -在hello uni-app x中,有native-button的完整示例。集成native-button的页面在pages/component/native-view/native-view.uvue,native-button组件在uni_modules/native-button/components/native-button/中。 - -## 总结@sum - -通过vue方式开发组件非常直观。它分为几个核心步骤: -1. 在uni_modules/xxx/components/xxx/xxx.uvue文件中,通过标准vue方式定义组件的属性、方式、事件 -2. 在uni_modules/xxx/components/xxx/xxx.uvue文件中,提供native-view组件,用于和原生的view绑定。在native-view组件的init事件中,调用utssdk下封装的原生对象的new初始化,将native-view对应的UniNativeViewElement传入 -3. 在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,通过uts的方式,定义原生对象,在构造时接收components/xxx/xxx.uvue组件传来的UniNativeViewElement,并创建一个真正的原生view,和UniNativeViewElement绑定。 -4. 在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,定义原生对象的各种方法,供components/xxx/xxx.uvue组件在其属性变化和方法调用时调用。 \ No newline at end of file + +## 开发UTS插件-标准模式组件 + +下面我们以一个例子来讲解标准模式组件的开发。 + +我们开发一个`native-button`组件,目标是把Android和iOS的原生button封装成uvue组件。 + +Android的原生button会带有水波纹效果。uni-app自带的button组件并没有这个效果。 + +该组件计划提供一个 text属性,用于显示按钮的文字;有一个buttonTap事件用于处理点击。 + +let's go! + +### 新建标准模式组件 + +HBuilder X 选中你的项目,项目根目录选中`uni_modules`目录,右键选择新建`uni_modules`插件,弹窗后分类选择 “UTS插件-标准模式组件”,填写组件名称,以下均以 `native-button` 为例 + +![](https://web-ext-storage.dcloud.net.cn/doc/uts/uts_plugin/create-uts-vue-component.png) + +创建完毕 HBuilder X 会自动创建一批模版文件,参考:[前述目录结构](#dir) + +### 标准模式组件功能实现 + +#### 添加 native-view + +上一步创建标准模式组件(名称为native-button)后,HBuilder X 会自动创建components/native-button/native-button.uvue文件。 + +这个文件是一个标准的uvue组件,符合easycom规范,在这个文件编写组件的属性、事件。 + +首先在该文件的template区添加 [native-view 组件](../component/native-view.md) + +```html + +``` + +#### native-view 与 原生对象关联 + +native-view 组件的用途就是提供一个占位view,并且可以和原生的view进行绑定。 + +native-view 组件初始化会触发 @init 事件,如下代码在init时创建原生NativeButton对象,在其内部实现了view的绑定。 + +[NativeButton](#utscode)是在utssdk目录的app-android和app-ios目录下的index.uts中定义的原生对象。NativeButton对象内部处理原生view与native-view绑定关联业务。 + +native-button.uvue代码中用NativeButton对象调用插件相关的API。 + +native-view 组件在uts中对应着UniNativeViewElement对象,将 UniNativeViewElement 传递给NativeButton对象,进行关联绑定。 + + +::: preview + +> 组合式 API + +```html + + +``` + +> 选项式 API + +```html + + +``` + +::: + +#### 组件声明方法 + +vue中,为组件定义方法很简单,但分选项式和组合式。 + +选项式中,在 methods 节点中添加updateText方法;组合式中,直接定义function updateText。参考vue文档[页面调用vue组件方法](https://doc.dcloud.net.cn/uni-app-x/vue/component.html#page-call-component-method) + +native-button组件使用者可调用该updateText方法中更新native-button文字。 + +但在vue组件的updateText方法中,需再次调用NativeButton的updateText方法,在原生插件中实现按钮文字更新。 + +::: preview + +> 组合式 API + +```ts + +``` + +> 选项式 API + +```ts +methods: { + //对外函数 + updateText(value: string) { + this.button?.updateText(value) + } +} +``` + +::: + +#### 组件声明属性props + +native-button 声明组件属性props,例如native-button的文案信息text属性,按vue组件规范监听到text属性更新,通过NativeButton对象驱动更新原生view属性,在components/native-button/native-button.uvue编写如下代码,具体参考vue文档[vue组件Props规范](https://cn.vuejs.org/guide/typescript/composition-api#typing-component-props) + +::: preview + +> 组合式 API + +```html + +``` + +> 选项式 API + +```html + +``` + +::: + +#### 组件声明事件 + +native-button 声明事件,例如原生组件触发点击事件@buttonTap, NativeButton对象通过 UniNativeViewElement 的 dispatchEvent 函数触发native-view的 @customClick 自定义事件。native-button.uvue监听native-view的 @customClick 自定义事件实现emit触发声明事件,具体参考[vue组件事件规范](https://cn.vuejs.org/guide/typescript/composition-api#typing-component-emits) + +::: preview + +> 组合式 API + +```html + + +``` + +> 选项式 API + +```html + + +``` + +::: + +**注意:** + +目前自定义事件参数仅支持[UniNativeViewEvent](../component/native-view#uninativeviewevent) + +native-button/components/native-button/native-button.uvue 最终代码如下: + +::: preview + +> 组合式 API + +``` html + + +``` + +> 选项式 API + +```html + + +``` + +::: + +#### 实现NativeButton对象@utscode + +utssdk目录实现不同平台的原生NativeButton对象,构造参数获取UniNativeViewElement对象与原生view绑定,封装原生view功能关联的API。 + +::: preview + +> Android + +```uts +import { Button } from "android.widget" + +export class NativeButton { + $element : UniNativeViewElement; + + constructor(element : UniNativeViewElement) { + //接收传递过来的UniNativeViewElement + this.$element = element; + this.bindView(); + } + + button : Button | null = null; + bindView() { + //通过UniElement.getAndroidActivity()获取android平台activity 用于创建view的上下文 + this.button = new Button(this.$element.getAndroidActivity()!); //构建原生view + //限制原生Button 文案描述不自动大写 + this.button?.setAllCaps(false) + //监听原生Button点击事件 + this.button?.setOnClickListener(_ => { + const detail = {} + //构建自定义UniNativeViewEvent返回对象 + const event = new UniNativeViewEvent("customClick", detail) + //触发原生Button的点击事件 + this.$element.dispatchEvent(event) + }) + //UniNativeViewEvent 绑定 安卓原生view + this.$element.bindAndroidView(this.button!); + } + + updateText(text: string) { + //更新原生Button 文案描述 + this.button?.setText(text) + } + + destroy(){ + //数据回收 + } +} +``` + +> iOS + +```uts +import { UIButton, UIControl } from "UIKit" + +export class NativeButton { + + element : UniNativeViewElement; + button : UIButton | null; + + constructor(element : UniNativeViewElement) { + // 接收组件传递过来的UniNativeViewElement + this.element = element; + super.init() + this.bindView(); + } + + // element 绑定原生view + bindView() { + // 初始化原生 UIButton + this.button = new UIButton(type=UIButton.ButtonType.system) + // 构建方法选择器 + const method = Selector("buttonClickAction") + // button 绑定点击回调方法 + button?.addTarget(this, action = method, for = UIControl.Event.touchUpInside) + // UniNativeViewElement 绑定原生 view + this.element.bindIOSView(this.button!); + } + + updateText(text : string) { + // 更新 button 显示文字 + this.button?.setTitle(text, for = UIControl.State.normal) + } + + /** + * 按钮点击回调方法 + * 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。 + */ + @objc buttonClickAction() { + //构建自定义 UniNativeViewEvent 对象 + let event = new UniNativeViewEvent("customClick") + //触发自定义事件 + this.element.dispatchEvent(event) + } + + destroy() { + // 释放 UTS 实例对象,避免内存泄露 + UTSiOS.destroyInstance(this) + } +} +``` + +::: + +更多实现可参考 标准模式组件 [native-button](https://gitcode.net/dcloud/hello-uni-app-x/-/tree/dev/uni_modules/native-button) + +此时一个简单的UTS插件-标准模式组件就完成了, + +**注意:** ++ UTS插件-标准模式组件的 components 目录下的代码中不应该含有原生平台任何引用对象,这会导致vue原生组件无法跨平台,推荐与原生平台关联的代码都放在utssdk中 ++ 绑定原生 view 方法(bindAndroidView、bindIOSView)仅支持调用一次,原生 view 一旦绑定后不支持再次绑定其他 view ++ ios平台需要vue组件主动释放 uts 实例,所以页面触发 unmounted 生命周期时需要调用 this.button?.destroy() 避免内存泄露 ++ android平台 native-view 组件不支持border、background、box-shadow属性,可以使用view标签包裹native-view,在view标签设置以上属性 + + +### 页面引用UTS插件-标准模式组件@pagecode + +以 native-button 为例, 创建标准模式组件的项目页面可以直接使用 native-button 标签,也可将native-button插件包放置其他项目的uni-modules文件夹中。项目页面即可使用 native-button 标签 + +```html + + + + + +``` + +在hello uni-app x中,有native-button的完整示例。集成native-button的页面在pages/component/native-view/native-view.uvue,native-button组件在uni_modules/native-button/components/native-button/中。 + +## 总结@sum + +通过vue方式开发组件非常直观。它分为几个核心步骤: +1. 在uni_modules/xxx/components/xxx/xxx.uvue文件中,通过标准vue方式定义组件的属性、方式、事件 +2. 在uni_modules/xxx/components/xxx/xxx.uvue文件中,提供native-view组件,用于和原生的view绑定。在native-view组件的init事件中,调用utssdk下封装的原生对象的new初始化,将native-view对应的UniNativeViewElement传入 +3. 在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,通过uts的方式,定义原生对象,在构造时接收components/xxx/xxx.uvue组件传来的UniNativeViewElement,并创建一个真正的原生view,和UniNativeViewElement绑定。 +4. 在uni_modules/xxx/utssdk/app-android 和 app-ios 下的/index.uts文件中,定义原生对象的各种方法,供components/xxx/xxx.uvue组件在其属性变化和方法调用时调用。