RISC-V生态开发套件解析(七):LicheeRV 86开发板快速开始Waft应用

简介: 随着RISC-V生态的蓬勃发展,相关开源开发套件也开始逐渐丰富。为了帮助开发者快速了解、玩转新推出的RISC-V开发套件,OCC推出RISC-V生态开发套件解析系列内容,详细讲解生态开发套件的功能特点与上手教程。

编辑语:

随着RISC-V生态的蓬勃发展,相关开源开发套件也开始逐渐丰富。为了帮助开发者快速了解、玩转新推出的RISC-V开发套件,OCC推出RISC-V生态开发套件解析系列内容,详细讲解生态开发套件的功能特点与上手教程。


通过上期内容的介绍,许多开发者已经初步了解了Waft应用的开发,并完成了Waft运行环境的搭建。本期内容旨在加深大家对Waft应用开发的了解,我们将通过拆解Waft应用的开发步骤,手把手教大家创建一个Waft应用。


01 开发环境支持


MacOS,Linux(Windows支持wsl、linux虚拟机)


02 waft开发流程


图片.png


03 安装waft-cli 工具


PS: 权限问题使用sudo执行即可


npm i waft-cli -g


使用 Windows 的开发者,可以安装官方推荐的wsl,推荐安装Linux虚拟机-Ubuntu(18.04、20.04), Linux 的发行版本推荐安装 Ubuntu(18.04、 20.04), 可在微软商店中下载。之后可在对应的 Linux 环境中执行开发所需命令。


wal网址:

https://docs.microsoft.com/en-us/windows/wsl/install?spm=a2cl5.25411629.0.0.2c5a180fdX4SIu



Ubuntu网址:https://www.microsoft.com/zh-cn/p/ubuntu-2004-lts/9n6svws3rx71?spm=a2cl5.25411629.0.0.2c5a180fdX4SIu&rtc=1#activetab=pivot:overviewtab


04 创建项目


通过waft脚手架初始化项目,会引导您进行项目命名等,您将得到一个新project


需要Node 14版本以上


waft init


图片.png

image.gif


这里我们选择第9个模板,平头哥天气Demo


05 启动调试服务


cd my-waft-project
npm run start


REPL命令行模式

启动后自动开启REPL模式,您可以通过.help查询支持哪些命令列表。


打包


waft>.build --aot=true --aotTarget=riscv64


编译后的产物在工程目录的build目录下,产物名称为app.aot,示例视频如下。

图片.png


文件夹及目录说明:


图片.png


06 推送


方式1(adb push):

电脑与开发板用type-c数据线连接,注意使用adb push通道,参考下图标注

image.gif图片.png


adb push build/app.aot /mnt/UDISK/wasm/


方式2(scp):

pc及开发板需要在同一个局域网内。


scp build/app.aot root@172.16.1.36:/mnt/UDISK/wasm


172.16.1.36替换为开发板的ip地址,ssh的登陆密码为:tina。


07 运行waft


通过adb shell或者串口接入开发板,在adb shell终端或者串口工具终端输入如下命令:


waft_app /mnt/UDISK/wasm/app.aot


示例运行界面:


image.gif图片.png


模拟器调试

当前只支持Mac模拟器    部分API不支持


点击面板中的启动模拟器,初次会自动下载模拟器(时间较长,需要等待一会)。


完整可以参考此文档:

https://www.yuque.com/waft/docs/dywumg_wk97d5?spm=a2cl5.25411629.0.0.77da180f7fYw5F


Web调试(Beta)

Web调试是通过将页面跨平台到Web端进行运行和渲染。由于Web端样式一致性仍在建设中,所以尽量以真机和模拟器的效果为准。


可以通过start时提示的链接打开进入。


08 布局和样式


1. 布局写法和数据绑定


Waft基于核心的响应式的数据绑定模块,来实现逻辑层修改数据,就能驱动视图层的更新的效果。


视图代码:


<div>
  <div>{{title}}</div>
  <div onTap="tapMe">示例按钮</div>
</div>


逻辑脚本:


let page: Login;
export class Login extends Page {
  constructor(props: ComponentProps) {
    super(props);
    page = this; // assemblyScript不支持闭包,在闭包中需要先赋给全局变量
    this.addEventListener('tapMe', function () {
      page.setState(`{"title":"Hello Waft"}`);
    });
  }
  onLoad(query: JSONObject): void{
    console.log('onload')
  }
}


如上所示,只要点击示例按钮,就会触发执行tapMe的函数回调,从而进行title字段的状态更新,视图因此会根据状态更新内容。


2.样式写法


Waft支持了主流的css样式,以及web规范的css写法,布局的单位为rpx,示例如下:


.title-div{
  width: 30rpx;
  height: 10rpx;
  background-color: red;
}
.title-text{
  font-size: 20rpx;
  color: #FFFFFF;
}


目前对rules规则如@media,css变量等能力暂未支持,具体可以参考ACSS规范:https://www.yuque.com/waft/docs/taglw5


3. 布局基准


默认框架的布局基准为1024px(指的是布局设计的全屏宽度像素)。


全屏应用:可以在app.json配置中自定义应用的基准。比如天猫精灵全屏的应用可以配置为1024。


{
  "pages": [
    "pages/index/index"
  ],
  "widgets":[
    "widgets/weather/weather"
  ]
  "window": {
    "defaultTitle": "Hello Waft"
  },
  "viewport": 1024
}


widget:需要在具体的某个widget的.json文件下配置,如果样式基准为300px来布局,可以配置viewport字段为300,如下:


{
  "usingComponents": {
    "card-layout": "waft-ui/src/components/card-layout/card-layout"
  },
  "viewport": 300
}


09 页面逻辑写法

页面逻辑的写法示例如下:


1. Function写法


import { JSON, JSONArray, JSONObject } from "waft-json";
import { getDataSource, log, FuncPage } from "waft";
let thisPage: FuncPage;
export function Index(page: FuncPage): void{
  thisPage = page;
  // 设置默认state
  page.setState(getDataSource().toString());
  page.onload = function (query: string) {
    log('--> onload:' + query);
  };
  page.onshow = function (event: string) {
    log('--> onshow:' + event);
  };
  page.onhide = function (event: string) {
    log('--> onhide:' + event);
  };
  page.onunload = function (event: string) {
    log('--> onunload:' + event);
  };
  page.addEventListener('tapTitle', function (event: string) {
    log('--> tapTitle event:' + event);
    thisPage.setState(`{"title":"Hello Waft"}`);
  });
}


2. Class写法


import { JSON, JSONObject } from "waft-json";
import { console, getDataSource, Page, ComponentProps, BaseEvent } from "waft";
let thisPage: Page;
export class Index extends Page {
  constructor(props: ComponentProps){
    super(props);
    thisPage = this;
    // 设置默认的state
    this.setState(JSON.stringify(getDataSource()));
    this.addEventListener('tapTitle', function (event: BaseEvent) {
      console.log('tapTitle event');
      thisPage.setState(`{"title":"Hello Waft"}`);
    });
  }
  onShow(): void{
    // 页面显示
    console.log('page onShow');
  }
  onLoad(query: JSONObject): void{
    // 页面加载后
    console.log('page onLoad:' + JSON.stringify(query));
  }
  onHide(): void{
    // 页面隐藏
    console.log('page onHide');
  }
  onUnLoad(): void{
    // 页面销毁
    console.log('page onUnLoad');
  }
  onMessage(data: JSONObject): void{
    // 信息推送更新
    console.log('page onMessage:' + JSON.stringify(data));
  }
  onError(error: Error): void{
    // 错误
    console.log('page onError');
  }
}


10 Page开发示例


根据模板创建页面

在src/pages下新建页面demo,包含了demo.axml,demo.acss,demo.ts,demo.json4个文件


在app.json中配置页面


{
  "pages": [
    "pages/demo/demo"
  ],
  "window": {
    "defaultTitle": "Hello Waft"
  }
}


【可选】在app.json配置页面渲染基准:

waft支持配置viewport。viewport代表了视觉布局的卡片总宽度基准(手机上都按750px布局),如果你的页面设计宽度总像素是按1024px布局,那只要设置viewport为1024,css即可按照1024rpx来写。(可以不配置,默认waft会按1024px来布局)


{
  "pages": [
    "pages/demo/demo"
  ],
  "window": {
    "defaultTitle": "Hello Waft"
  }
  "viewport": 1024
}


【可选】在mock.json中配置页面mock启动参数:

启动参数包含了以下值:

  • path: 启动页面路径;(默认为首页)
  • query: 启动的query参数
  • dataSource:启动的额外下发数据 (如服务端预先请求完数据,会放到dataSource下)


可以在src目录下的mock.json文件中配置数据,该数据可以在运行环境中通过 getLaunchData() 函数调用。


会在实际下发时按照实际运行,该参数只影响调试环境,不影响生产运行环境。


{
  "path": "pages/demo/demo",
  "query": {
    "id": "123456"
  }
  "dataSource":{
    "title": "hello"
  }
}


在axml文件中开发界面:

开发界面和数据绑定


<div>
  <div>{{title}}</div>
</div>


在ts文件中开发逻辑:

  • 可以在页面初始化时,通过全局的getLaunchData()方法,获取到应用启动的信息

  • 取出其中的dataSource字段,设置到默认的state
  • 在生命周期中,可以进行您的定制操作


import { JSON, JSONObject } from "waft-json";
import { console, getDataSource, WaftPage, ComponentProps } from "waft";
export class Index extends WaftPage {
  constructor(props: ComponentProps){
    super(props);
    this.setState(JSON.stringify(getDataSource()));
  }
  onShow(): void{
    console.log('page onShow');
  }
  onLoad(query: JSONObject): void{
    console.log('page onLoad:' + JSON.stringify(query));
  }
  onHide(): void{
    console.log('page onHide');
  }
  onUnLoad(): void{
    console.log('page onUnLoad');
  }
  onMessage(data: JSONObject): void{
    console.log('page onMessage:' + JSON.stringify(data));
  }
  onError(error: Error): void{
    console.log('page onError');
  }
}


11 waft-router


waft框架提供了多页路由的api。


在目录里新建多个页面,并在app.json中配置

image.gif

图片.png


在app.json中配置页面,和默认启动页

图片.png


在页面中使用history API跳转

push

跳转路由界面


const query = new JSONObject();
query.set("id", 123);
// query可以省略 或用 null 或 new JSONObject()
history.pushState({url : 'pages/detail/detail', query: query });


replace

替换当前页面,换为路由界面


// query可以省略 或用 null 或 new JSONObject()
history.replaceState({url : 'pages/detail/detail', query: JSON.parseObject(`{"id":"123456"}`)});


goBack

返回上一页


history.goBack();


12 waft-store

waft提供了全局状态store。


store数据获取


improt { store } from 'waft';
const globalData = store.getGlobalData();


store设置数据


import { store } from 'waft'
store.dispatch('state', new JSONObject())


store更新订阅

在component或者page中,可以通过this.observer方法监听全局store的更改。


immediate参数标识是否默认立即返回初始的状态。


export class Login extends Page {
  constructor(props: ComponentProps) {
    super(props);
    // 监听全局store变化
    this.observer(['menuData'], (key:string, data: JSONObject)=>{
      console.log('menuData change:' + data.toString());
    }, {
      immediate: true
    });
  }
}


store默认映射到当前页面的state

在component或者page中,可以通过this.connect方法把store中的内容订阅并同步到page的state上。


第二个参数可以传入一个reducer,修改参数再返回。return null时不处理。


export class Login extends Page {
  constructor(props: ComponentProps) {
    super(props);
    // 自动把store的key内容同步到page的state
    this.connect(['menuData']);
    // 监听全局store变化,并修改; 
    this.connect(['menuData'], (key:string, data: JSONObject, oldData: JSONObject | null)=>{
      return data;
    });
  }
}


附:

waft开发手册:https://www.yuque.com/waft/docs/ubi8k4


13 下期预告


本期内容就介绍到这里,下期我们将带大家上手Button的使用,欢迎大家持续关注RISC-V生态开发套件系列内容。

相关文章
|
3天前
|
Java
并发编程之线程池的应用以及一些小细节的详细解析
并发编程之线程池的应用以及一些小细节的详细解析
16 0
|
3天前
|
SQL 存储 关系型数据库
数据库开发之图形化工具以及表操作的详细解析
数据库开发之图形化工具以及表操作的详细解析
19 0
|
22天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
3天前
|
SQL 存储 关系型数据库
数据库开发之mysql前言以及详细解析
数据库开发之mysql前言以及详细解析
14 0
|
25天前
|
存储 缓存 算法
Python中collections模块的deque双端队列:深入解析与应用
在Python的`collections`模块中,`deque`(双端队列)是一个线程安全、快速添加和删除元素的双端队列数据类型。它支持从队列的两端添加和弹出元素,提供了比列表更高的效率,特别是在处理大型数据集时。本文将详细解析`deque`的原理、使用方法以及它在各种场景中的应用。
|
8天前
|
Java API 数据库
深入解析:使用JPA进行Java对象关系映射的实践与应用
【4月更文挑战第17天】Java Persistence API (JPA) 是Java EE中的ORM规范,简化数据库操作,让开发者以面向对象方式处理数据,提高效率和代码可读性。它定义了Java对象与数据库表的映射,通过@Entity等注解标记实体类,如User类映射到users表。JPA提供持久化上下文和EntityManager,管理对象生命周期,支持Criteria API和JPQL进行数据库查询。同时,JPA包含事务管理功能,保证数据一致性。使用JPA能降低开发复杂性,但需根据项目需求灵活应用,结合框架如Spring Data JPA,进一步提升开发便捷性。
|
11天前
|
SQL API 数据库
Python中的SQLAlchemy框架:深度解析与实战应用
【4月更文挑战第13天】在Python的众多ORM(对象关系映射)框架中,SQLAlchemy以其功能强大、灵活性和易扩展性脱颖而出,成为许多开发者首选的数据库操作工具。本文将深入探讨SQLAlchemy的核心概念、功能特点以及实战应用,帮助读者更好地理解和使用这一框架。
|
13天前
|
机器学习/深度学习 分布式计算 BI
Flink实时流处理框架原理与应用:面试经验与必备知识点解析
【4月更文挑战第9天】本文详尽探讨了Flink实时流处理框架的原理,包括运行时架构、数据流模型、状态管理和容错机制、资源调度与优化以及与外部系统的集成。此外,还介绍了Flink在实时数据管道、分析、数仓与BI、机器学习等领域的应用实践。同时,文章提供了面试经验与常见问题解析,如Flink与其他系统的对比、实际项目挑战及解决方案,并展望了Flink的未来发展趋势。附带Java DataStream API代码样例,为学习和面试准备提供了实用素材。
35 0
|
14天前
|
监控 测试技术 Android开发
移动应用与系统:开发与操作系统的深度解析
【4月更文挑战第11天】在这篇文章中,我们将深入探讨移动应用的开发过程,以及移动操作系统如何影响这些应用的性能和功能。我们将详细分析移动应用开发的关键步骤,包括需求分析、设计、编码、测试和维护。同时,我们也将探讨移动操作系统,如Android和iOS,如何为应用开发提供支持,并影响其性能。
|
21天前
|
测试技术 API 智能硬件
语言模型在提升智能助手引用解析能力中的创新应用
【4月更文挑战第4天】苹果研究团队推出了ReALM,一种利用大型语言模型解决引用解析的新方法,提升智能助手理解用户意图和上下文的能力。ReALM将引用解析转化为语言建模问题,尤其擅长处理屏幕上的实体,比现有系统提升超5%,性能接近GPT-4但参数更少。其模块化设计易于集成,可在不同场景下扩展。然而,复杂查询处理和依赖上游数据检测器可能影响其准确性和稳定性。
63 6
语言模型在提升智能助手引用解析能力中的创新应用

推荐镜像

更多