鸿蒙JS开发项目总结
第一部分 鸿蒙JS基础入门
Project Type:
- Service 没有界面, 只提供数据服务
- Application 有界面, 提供数据服务
- 鸿蒙不能打印对象, 只能打印字符串
console.log('888:' +JSON.stringify(data))//对象转字符串打印
const target = JSON.parse(res.data)//把JSON规则的字符串转换为JSONObject
-
预览器会默认被当做PC环境, 无法请求数据, 建议用真机/模拟器来调试网络请求
-
build生成的不是apk, 而是.hap
-
想要实现可视化编程: /js/default/pages 右键-->New-->JS Visual
1.不同设备
在.css中:
//不同设备之间的样式设置
@media screen and (device-type: wearable){
.title{
font-size: 20px;
color: #ffffff;
}
}
@media screen and (device-type: phone) and (orientation: landscape){
.title{
font-size: 60px;
}
}
2.导入资源使用
/// 在路径 common/datas/ 下 新建frames.js:
export default[
{
//⚠️通过js去引进图标文件的时候, 一定要使用绝对路径
src: "/common/images/other/0.jpg",
},
{
src: "/common/images/other/1.jpg",
},
...
]
/// 在其他js文件中, 使用frames.js的资源;
import frames from "../../common/datas/frames.js"
//⚠️在js中导入第三方数据的时候, 一定要使用相对路径
export default{
data:{
frames,
},
handleStart(){
this.$refs.animator.start();
},
...
},
3.TodoList应用构建
页面样式设计注意事项
- 页面css支持id、class、tag选择器, 建议使用class选择器
- 页面样式基于flex弹性布局进行设置, 默认是flex弹性布局, 需要注意, 弹性布局会自动的拉升和压缩内部元素模块宽度、高度
- 鸿蒙封装的js组件, 有个专门的样式说明, 与传统CSS写法有很大差异
示例:
在js/defalut/common/datas/todoList.js中:
//第三方 JSON 数据导入,注意使用相对路径
export default [
{
info: '给老王打个电话',
status: true
},
{
info: '输出工作计划',
status: false
},
{
info: '和小王对接需求',
status: true
},
{
info: '整理客户资料',
status: false
},
{
info: '和朋友一起聚餐',
status: false
}
]
在index.html中:
<div class="container">
<text class="title">待办事项</text>
<div class="item" for="{{todoList}}">
<text class="todo">{{$item.info}}</text>
<switch showtext="true" checked="{{ $item.status }}"
texton="完成" textoff="待办"
class="switch"></switch>
<button class="remove" onclick="remove($idx)">删除</button>
</div>
<div class="info">
<text class="info-text">您还有</text>
<text class="info-num">{{todoCount()}}</text>
<text class="info-text">件事情待办,加油!</text>
</div>
<div class="add-todo">
<input class="plan-input" type="text"></input>
<button class="plan-btn" onclick="addTodo">添加待办</button>
</div>
</div>
在index.js中:
import todoList from "../../common/datas/todoList.js"
export default {
data: {
todoList
},
//普通事件
remove(index){
console.log(index)
this.todoList.splice(index, 1)
},
switchChange(index){
this.todoList[index].status = !this.todoList[index].status
},
addTodo(){
this.todoList.push({
info:'IDE工具无法监听键盘输入',
status: false
})
},
//定义计算属性
computed:{
todoCount(){
let num = 0;
this.todoList.forEach(element=>{
if(!element.status){
num++
}
})
return num
}
}
}
4.多端设备规则
在手机P40设备上1px = 3物理像素
在TV设备上1px = 2 物理像素
在穿戴wearable设备上 1px = 2 物理像素
// 我们常用类型来进行判断,按照 phone、tv、wearable 顺序输出不同响应式的页面布局
@media screen and (device-type: phone) {}
@media screen and (device-type: tv) {}
@media screen and (device-type: wearable) {}
5.路由传参
// 页面跳转并传参
switch(index){
case 0:
router.push({
uri:"pages/index/index",
params:{
info:"这是路由传递的参数"
}
});
break;
case 1:
...
}
// 接收页面跳转后传递过来的参数, 在index.html中直接使用:
<text>{{info}}</text>
6.项目配置
{
"app": {
"bundleName": "net.newsmth.newsmthcard", //包名
"vendor": "newsmth",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "net.newsmth.newsmthcard",
"name": ".MyApplication",
"mainAbility": "net.newsmth.newsmthcard.MainAbility",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "portrait",//固定手机竖向展示
"visible": true,
"name": "net.newsmth.newsmthcard.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
},
{
"name": "net.newsmth.newsmthcard.DetailAbility",
"icon": "$media:icon",
"description": "$string:detailability_description",
"label": "$string:entry_DetailAbility",
"type": "page",
"launchType": "standard"
}
],
"js": [
{
"pages": [
"pages/index/index",
"pages/detail/index"
],
"name": "default",
"window": {
"designWidth": 720,
"autoDesignWidth": true
}
}
]
}
}
很多功能JS实现不了, 比如数据库, 需要使用java
7.卡片布局判断
<div class="grid_pattern_layout">
<!-- 1*2-->
<div if="{{ mini }}" class="mini_container">
<image src="/common/image_1.png" class="mini_image"></image>
<text class="mini_text">标题mini</text>
</div>
<!-- 2*2-->
<div class="normal_container">
<!-- 2*4-->
<div if="{{ dim2X4 }}" class="preview_container">
</div>
<!-- 4*4-->
<div class="detail_container">
</div>
</div>
</div>
8.toast
import prompt from '@system.prompt';
export default {
test1(e) {
//触发弹窗
prompt.showToast({
message: '弹窗内容'
})
},
}
第二部分 服务卡片
1.service Widget(服务卡片)
-
显示卡片的方法:
1.按住App的图标, 向上滑动, 当手指划出图标后会弹出卡片. 例如, 运动健康, 12的卡片和22的卡片 2*4
-
2.直接将卡片放到桌面上:
(1)使用1的方式弹出卡片, 然后点击右上角的图钉
(2)按住App的图标, 然后点击"服务卡片",然后选择相应的卡片, 点击"添加到桌面"
(3)长按桌面已有卡片, 然后点击"更多服务卡片"进行选择
-
-
服务卡片的事件 -—- 与宿主程序进行交互的四个方法(在java/MainAbility.java中)
- onCreateForm(Intent intent) 卡片创建时触发
- onUpdateForm(long formld) 卡片更新时触发, formld:卡片对应的id
- onDeleteDorm(long formld) 卡片删除时触发
- onTriggerFormEvent(long formld, String message) 卡片与宿主程序交互时触发
如何同时控制多个服务卡片
// 在java/MainAbility.java中:
@Override
protected ProviderFormInfo onCreateForm(Intent intent) {
HiLog.info(TAG, "onCreateForm");
long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
// 将每一个创建的服务卡片的formid保存到list中
}
@Override
protected void onDeleteForm(long formId) {
//删除不需要的服务卡片
}
2.行内样式
标签显示模式转换 display块转行内:display:inline
;
行内转块:display:block
;
块、行内元素转换为行内块: display: inline-block
;
比如实现like评论结尾的"删除"按钮:
<text class="content">
<span>{{info.name}}:{{info.content}}</span>
<span if="{{info.canDelete}}" class="delete" @click="delete">删除</span>
</text>
3.鸿蒙UI框架生命周期
JS UI的Ability生命周期
下面是几个主要生命周期函数。
● onCreate ()
当应用创建时调用。(应用的生命周期)
● onInit ()
页面数据初始化完成时触发,只触发一次。
● onReady ()
页面创建完成时触发,只触发一次。
● onShow ()
页面显示时触发。
● onHide ()
页面消失时触发。
● onDestroy ()
页面销毁时触发
4.鸿蒙js开发暗黑模式适配
@media screen and (dark-mode: true){
.title{
color: aliceblue;
}
}
方案二: 关闭暗黑模式追随系统
config.json里module层级下有个colorMode,可以根据需要设置light/dark/auto
5.js 中编码(encode)和解码(decode)的三种方法
unescape, decodeURI, decodeURIComponent✅
6.js map的key排序
* map排序 对map的key值进行排序
* @param map
* @param sortFunc
* eg:
* let map = {
* key1: { name: 'wdf', sortid: 10 },
* key2: { name: 'wwx', sortid: 1 },
* key3: { name: 'sss', sortid: 5 },
* }
* map = sortMap(map, (a, b) => { return a.sortid - b.sortid })
*/
function sortMap(map: {}, sortFunc?: (v1, v2) => number) {
let keys = Object.keys(map)
let sortkeys = keys.sort(sortFunc)
let sortMap = {}
sortkeys.forEach(k => { sortMap[k] = map[k] })
map = sortMap
return map
}
7.js中get请求中将json格式的对象拼接成复杂的url参数
const queryStr = Object.keys(query)
.reduce((ary, key) => {
if (query[key]) {
ary.push(encodeURIComponent(key) + '=' + encodeURIComponent(query[key]));
}
return ary;
}, [])
.join('&');
url += `?${queryStr}`;
8.前端js几种加密/解密方法
9.Promise和Async/await的理解和使用
https://www.wolai.com/x3SycgxN1kUXKjrUA2y4jh#7Le4q5RCZcGfeRF2N6NrMR