【每日学点鸿蒙知识】Web跳转系统应用、页面动态跳转、非UI中观测变化、MVVM模式、循环中使用定时问题
1、HarmonyOS Web组件中怎么拨打电话、跳转应用商店?
拨打电话demo:
import web_webview from ‘@ohos.web.webview’;
import call from ‘@ohos.telephony.call’;
import { BusinessError } from ‘@ohos.base’;
@Entry
@Component
struct WebComponent {
webviewController: web_webview.WebviewController = new web_webview.WebviewController();
build() {
Column() {
Web({ src: $rawfile(‘call.html’), controller: this.webviewController})
.onLoadIntercept((event) => {
if (event) {
let url: string = event.data.getRequestUrl();
// 判断链接是否为拨号链接
if (url.indexOf(‘tel://’) === 0) {
call.makeCall(url.substring(6),(err: BusinessError) => {
if (!err) {
console.log(“make call success.”);
} else {
console.log(“make call fail, err is:” + JSON.stringify(err));
}
});
return true;
}
}
return false;
})
}
}
}
call.html:
<!DOCTYPE html> <html> <body> <div> <a href="tel://10086">拨打电话</a> </div> </body> </html>
跳转应用商店demo:
import Want from '@ohos.app.ability.Want';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
@State appId: string = 要跳转的AppID;
controller: TextInputController = new TextInputController();
build() {
Row() {
Column() {
TextInput({ text: this.appId, placeholder: '请输入应用的appId', controller: this.controller })
.width('90%')
.onChange((value: string) => {
this.appId = value
})
Button('点击跳转到HarmonyOS版应用市场详情页面')
.margin({top: 50})
.onClick(()=>{
const want: Want = {
uri: `store://appgallery.huawei.com/app/ id=${this.appId}`
};
const context = getContext(this) as common.UIAbilityContext;
context.startAbility(want).then(()=>{
//拉起成功
}).catch(()=>{
// 拉起失败
});
})
}
.width('100%')
}
.height('100%')
}
}
2、HarmonyOS 目前有一个页面,页面其中一部分的内容是动态的,根据不同的逻辑需要展现不同的页面,需要实现动态传入页面组件进行展示?
class Tmp {
paramA1: string = ''
}
@Builder function overBuilder(params: Tmp) {
Row() {
Text(`overBuilder: ${params.paramA1} `)
}
}
@Builder function overBuilder2(params: Tmp) {
Row() {
Text(`overBuilder2: ${params.paramA1} `)
}
}
@Entry
@Component
struct Index123 {
@State label: string = 'Hello';
@State buildSet: boolean = false;
build() {
Row() {
Column() {
if(this.buildSet){
overBuilder({ paramA1: this.label })
}else{
overBuilder2({ paramA1: this.label })
}
}
.width('100%')
}
.height('100%')
}
}
3、HarmonyOS 在非UI描述中观测变化?
如何在非UI描述中(如aboutToAppear)观测被@ObservedV2装饰的变量的变化?
aboutToAppear只有在创建页面的时候才会触发。aboutToAppear函数在创建自定义组件的新实例后,在执行其build()函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build()函数中生效。参考链接:
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-custom-component-lifecycle-V5#abouttoappear
4、HarmonyOS MVVM模式?
viewmodel怎么和view建立关系的
viewmodel数据变化的时候怎么通知view中的装饰器的?
应用示例电话簿的demo
被@State修饰的变量在被更新后因为会重新触发UI渲染,也就是会重新执行build方法,所以页面会实时显示更新的数据。@Provide也具有@State的特性,同时@Provide可以与@Consume搭配实现父、子和后代组件数据同步。关于这些装饰器的内容,可在官网文档中进行详细了解:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-component-state-management-V5
应用示例电话簿的demo如下
//Index.ets
import { Person, Address, AddressBook, ObservedArray} from '../viewmodel/ListViewModel'
import emitter from '@ohos.events.emitter';
// 渲染出Person对象的名称和Observed数组<string>中的第一个号码
// 为了更新电话号码,这里需要@ObjectLink person和@ObjectLink phones,
// 不能使用this.person.phones,内部数组的更改不会被观察到。
// 在AddressBookView、PersonEditView中的onClick更新selectedPerson
@Component
struct PersonView {
@ObjectLink person: Person;
@ObjectLink phones: ObservedArray<string>;
@Link selectedPerson: Person;
build() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
Text(this.person.name)
if (this.phones.length) {
Text(this.phones[0])
}
}
.height(55)
.backgroundColor(this.selectedPerson.name == this.person.name ? "#ffa0a0" : "#ffffff")
.onClick(() => {
this.selectedPerson = this.person;
})
}
}
@Component
struct phonesNumber {
@ObjectLink phoneNumber: ObservedArray<string>
build() {
Column() {
ForEach(this.phoneNumber,
(phone: ResourceStr, index?: number) => {
TextInput({ text: phone })
.width(150)
.onChange((value) => {
console.log(`${index}. ${value} value has changed`)
this.phoneNumber[index!] = value;
})
},
(phone: ResourceStr, index: number) => `${this.phoneNumber[index] + index}`
)
}
}
}
// 渲染Person的详细信息
// @Prop装饰的变量从父组件AddressBookView深拷贝数据,将变化保留在本地, TextInput的变化只会在本地副本上进行修改。
// 点击 "Save Changes" 会将所有数据的复制通过@Prop到@Link, 同步到其他组件
@Component
struct PersonEditView {
@Consume addrBook: AddressBook;
/* 指向父组件selectedPerson的引用 */
@Link selectedPerson: Person;
/*在本地副本上编辑,直到点击保存*/
@Prop name: string = "";
@Prop address: Address = new Address("", 0, "");
@Prop phones: ObservedArray<string> = [];
selectedPersonIndex(): number {
return this.addrBook.contacts.findIndex((person: Person) => person.id_ == this.selectedPerson.id_);
}
build() {
Column() {
TextInput({ text: this.name })
.onChange((value) => {
this.name = value;
})
TextInput({ text: this.address.street })
.onChange((value) => {
this.address.street = value;
})
TextInput({ text: this.address.city })
.onChange((value) => {
this.address.city = value;
})
TextInput({ text: this.address.zip.toString() })
.onChange((value) => {
const result = Number.parseInt(value);
this.address.zip = Number.isNaN(result) ? 0 : result;
})
if (this.phones.length > 0) {
phonesNumber({ phoneNumber: this.phones })
}
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
Text("Save Changes")
.onClick(() => {
// 将本地副本更新的值赋值给指向父组件selectedPerson的引用
// 避免创建新对象,在现有属性上进行修改
this.selectedPerson.name = this.name;
this.selectedPerson.address = new Address(this.address.street, this.address.zip, this.address.city)
this.phones.forEach((phone: string, index: number) => {
this.selectedPerson.phones[index] = phone
});
emitter.emit('setModelData', {
data: {
id: this.selectedPerson.id_,
name: this.name
}
})
})
Button('getData')
.onClick(() => {
emitter.emit('getModelData');
this.selectedPerson = this.addrBook.me;
})
if (this.selectedPersonIndex() != -1) {
Text("Delete Contact")
.onClick(() => {
let index = this.selectedPersonIndex();
console.log(`delete contact at index ${index}`);
// 删除当前联系人
this.addrBook.contacts.splice(index, 1);
// 删除当前selectedPerson,选中态前移一位
index = (index < this.addrBook.contacts.length) ? index : index - 1;
// 如果contract被删除完,则设置me为选中态
this.selectedPerson = (index >= 0) ? this.addrBook.contacts[index] : this.addrBook.me;
})
}
}
}
}
}
@Component
struct AddressBookView {
@ObjectLink me: Person;
@ObjectLink contacts: ObservedArray<Person>;
@State selectedPerson: Person = new Person("", "", 0, "", []);
aboutToAppear() {
this.selectedPerson = this.me;
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start }) {
Text("Me:")
PersonView({
person: this.me,
phones: this.me.phones,
selectedPerson: this.selectedPerson
})
Divider().height(8)
ForEach(this.contacts, (contact: Person) => {
PersonView({
person: contact,
phones: contact.phones as ObservedArray<string>,
selectedPerson: this.selectedPerson
})
},
(contact: Person): string => {
return contact.id_;
}
)
Divider().height(8)
Text("Edit:")
PersonEditView({
selectedPerson: this.selectedPerson,
name: this.selectedPerson.name,
address: this.selectedPerson.address,
phones: this.selectedPerson.phones
})
}
.borderStyle(BorderStyle.Solid).borderWidth(5).borderColor(0xAFEEEE).borderRadius(5)
}
}
@Entry
@Component
struct Index {
@StorageLink("contacts") @Watch("contactsChange") contacts: Array<Person> = [];
@Provide addrBook: AddressBook = new AddressBook(
new Person("Gigi", "Itamerenkatu 9", 180, "Helsinki", ["18*********", "18*********", "18*********"]),
[
new Person("Oly", "Itamerenkatu 9", 180, "Helsinki", ["11*********", "12*********"]),
new Person("Sam", "Itamerenkatu 9", 180, "Helsinki", ["13*********", "14*********"]),
new Person("Vivi", "Itamerenkatu 9", 180, "Helsinki", ["15*********", "168*********"]),
]);
contactsChange(propName: string): void {
this.addrBook.contacts = AppStorage.get(propName) as ObservedArray<Person>;
}
build() {
Column() {
AddressBookView({
me: this.addrBook.me,
contacts: this.addrBook.contacts,
selectedPerson: this.addrBook.me
})
}
}
}
viewmode和model通过状态变量进行数据更新后,viewmodel再通过状态变量的更新来触发view页面的build方法和@Builder自定义构建函数的执行;build方法和@Builder自定义构建函数的执行又会使相应的状态变量改变,如此实现“更新数据的时候直接更新视图”
5、HarmonyOS for循环里使用setTimeout无效,使用data空循环崩溃?
for循环里使用setTimeout无效,使用data空循环崩溃…如何在for循环里构造延时
//等待
const start = Date.now();
while (Date.now() - start < 1000) {
// 空循环,等待 1 秒
}
console.log(‘End blocking’);
参考这个 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/async-concurrency-overview-0000001632690002-V2 ,将 setTimeout包装为 promise,使用相关 api
原文地址:https://blog.csdn.net/sjw890821sjw/article/details/144798921
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!