自学内容网 自学内容网

【每日学点鸿蒙知识】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)!