专栏首页CSDN技术头条【独家】饿了么前端团队快应用背后研发实践

【独家】饿了么前端团队快应用背后研发实践

作者说:

饿了么是一年前开始参与内测尝试开发快应用的,看着快应用平台一步一步的走过来,发展的越来越好。目前来说快应用开发条件已经比较完善,本次分享,为大家介绍前端开发人员眼中快应用的开发与使用 Vue.js 开发的一些异同,以及通过实践积累出的一些方法的正确使用姿势。

面向的场景

目前快应用在饿了么中的用户场景为:

用户在「应用商店」、「浏览器」、「自带搜索助手」搜索饿了么,出现快应用的条目,用户点击饿了么快应用,无需安装,直接打开快应用。同时会提示用户是否生成桌面图标,并且用户可以收到来自服务进行的推送,体验和原生 App 相差无异。

开发工具与条件

开发快应用的前提是拥有一台九大厂商品牌之一的安卓手机,然后注册快应用联盟账号,接着与该手机对应品牌的开发者账号进行绑定,然后照着快应用的开发文档进行开发,最后上传至快应用官网进行测试审核并分发。

目前快应用还不能实现自动统一分发到各个平台去审核。如果想要在每个品牌的应用市场都上架自己的快应用,就需要每个平台的开发者账号都要去填写开发者信息,1-2工作日审核,然后再上架自己的快应用。

与前端的对比

页面布局

快应用整体基于 Fex 布局:

  • display 默认 flex,支持的参数为 flex | none;
  • position 默认 none,支持的参数为 fixed | none;
  • 宽、高、长度值只能使用 px 或 %。

页面标签

如果要将原生 HTML 布局迁移至快应用,需要注意的是快应用中没有 H1~H6 标签,同时一些 HTML5 标签例如<header> <footer> <article> 等都要做改动。

另外文本不能单纯放在 <div> 中,只能放在 <a> <span> <text> 标签中。

使用时要注意好嵌套关系,比如 <a> 标签的子组件只支持 <span> 标签,<text> 标签的子组件只支持 <a><span>

<img> 图片标签在快应用中用 <image> 标签替代。

<rating> 是原生 HTML 没有的,是用来显示星级的组件,显示星级在饿了么 App 中处处可见,这个功能非常实用,省去了我们手写去实现的时间。

Storage

快应用中打包后是一个 .rpk 程序,因此并不需要 sessionStorage。在快应用中,若想要做本地存储,可以直接使用 Storage 方法:

例如读取存储的用户信息,见下面代码。

storage.js:

import storage from '@system.storage'const User = () => {  return new Promise((resolve, reject) => {
    storage.get({
      key: 'USER',
      success: (currentUser) => {
        currentUser = currentUser && JSON.parse(currentUser)        if (!currentUser) {
          currentUser = undefined
        }
        resolve(currentUser)
      },
      fail: (err) => {
        reject(err)
      }
    })
  })
}export default {
  User
}

Home.ux:

import { User } from '../Common/service/storage'User().then((currentUser) => {  this.currentUser = currentUser;  this.loadData()
})

通过 storage.get、storage.set、storage.clear、storage.delete 可以随心所欲的操作存储我们的数据了。

与 Vue.js 的对比

使用过 Vue.js 的同学看了快应用的官方文档后会发现快应用的的 API 大量的借鉴了 Vue.js,甚至一些方法名也是一样的。虽然如此,但是二者一个是基于手机平台的新型应用状态,一个是构建用户界面的 Web 应用框架,在实际开发中还是有很多不一样的地方,下面简单介绍总结一下两者的异同。

开发环境及工具

快应用的开发环境对 NodeJS 的版本要求很严格,官方推荐安装 v6.11.3, 如果开发者本地的 NodeJS 版本过高,快应用的 Toolkit 工具安装时会报错,官方给的解释是:内部 ZipStream 实现与 node-archive 包不兼容。安装完 Toolkit 之后,也可以像 Vue.js 一样通过脚手架工具快速生成一个项目模板:

hap init <ProjectName>

除此之外,快应用还需要在手机上安装调试器和平台预览版,用来在开发过程中实时预览界面和开发调试平台新功能,最后可以按照官方的文档跑起这个文档项目。本地开发快应用推荐使用 VSCode,因为可以在 VScode 里下载官方推荐的 Hap Extension 插件。

而对于 Vue.js 而言,所有支持 Language Server Protocol 的编辑器都适合 Vue.js。因此主流的前端编辑器都支持 Vue.js 语法开发。

相对比而言,Vue.js 的对开发环境和开发工具的限制更小一些。但是一个是新起的快应用,另一个是有四年时间积累的 Vue.js ,自然不能这么去对比,快应用的开发条件的完善目前只是时间问题。

模板

模板定义

快应用和 Vue.js 都是使用 <template> 标签来定义模板,小程序也是如此。但是 Vue.js 中的模板的定义类型会更多一些。

自定义组件在模板中的引用

快应用中在模板中直接通过 import 进行引入,例如:

<import name='comp' src='./comp'></import><template>
  <div>
    <comp prop1='xxxx' onevent1="bindParentVmMethod1" @event-type1="bindParentVmMethod1"></comp>
  </div></template>

它也可以通过 (on|@) 语法绑定自定义子组件上的事件,Vue.js 是将自定义组件注册到 components 中再去引用。

生命周期

快应用的常用的生命周期如下:

生命周期

描述

onInit

可以开始使用页面中的数据

onReady

开始获取DOM节点(如:this.$element(idxxx) )

onShow

页面被切换重新显示时会被调用 onShow

onHide

页面被切换隐藏时调用 onHide

onDestroy

页面被销毁时调用

‍‍通过描述,我们可以用实践总结出一些这些生命周期实际的使用场景。

onInit
  • 获取或修改 localstorage 中存储的内容;
  • 获取全局对象及方法 例如:this.app.app.data.place.address;
  • 获取请求接口返回的数据。
onReady
  • 组件自定义事件的触发,例如:this.$dispatch('shopMenuReady')。
onShow

页面后退时触发,数据需重置,例如用户进入饿了么首页 -> 点击左上角进行修改地址 -> 进入地址页面 -> 选择地址 -> 自动返回到首页 -> onShow() 事件监听 -> 更新左上角的地址。

onHide

场景与 onShow 相反

onDestroy

该页面某个行为使用了 setInterval() 方法,离开该页面时在 onDestroy() 中 clearInterval 保证下次进入时仍是初始化的状态。

在 Vue 中生命周期除了上面的 onShow 和 onHide,其他差别不大,对于 Vue.js 中 onShow 可以用 watch 去监听路由变化来上述 onShow 中的场景,例如:‍‍

  watch: {    // 如果路由有变化,会再次执行该方法
    $route: 'initPageData'
  },  methods: {
    initPageData () {    // do something
    }
  }

数据绑定

内容绑定,两者采用的都是 Mustache 语法(双大括号),两者都可以在内容中插入 HTML。

快应用:

<text>{{ title }}</text><richtext>{{ message }}</text>

Vue.js:

<div>{{ title }}</div><div v-html="message">

条件与列表渲染

快应用的条件渲染有 if/elif/else 这3个相关指令,用于控制是否增加或者删除组件:

<text if="{{conditionVar === 1}}">if: if条件</text>
<text elif="{{conditionVar === 2}}">elif: elif条件</text>
<text else>else: 其余</text>

同时还有 show 指令,用于控制组件的显示状态,并不会从 DOM 结构中删除:

<text show="{{showVar}}">show: 渲染但控制是否显示</text>

列表渲染:

 <div class="city" for="city in cities">
  <text>城市:{{city.name}}</text></div>

Vue.js 的条件渲染:

<div v-if="type === 'A'">
  A</div><div v-else-if="type === 'B'">
  B</div><div v-else-if="type === 'C'">
  C</div><div v-else>
  Not A/B/C</div>

show 指令:

<h1 v-show="ok">Hello!</h1>

列表渲染:

<li v-for="todo in todos">
  {{ todo }}</li>

两者从使用逻辑上来说几乎没有什么区别,只是写法略有不同,但是快应用中增加了一个组件 <block>,可以使用 <block> 实现更为灵活的“列表/条件渲染”。

<block> 是一个仅表达逻辑的组件,并不会在页面渲染中生成 DOM 节点,这个可以说是很得人心。Vue.js 里面也有一些内置的不会产生 DOM 节点的组件,例如 <component><keep-alive><transition><transition-group><slot>。简单举个例子, 使用 Vue 保留的<component> 元素,将多个组件动态地绑定到 <component> 元素的 is 属性上。

<template><component :is="isSignedIn ? 'home' : 'welcome'"></component></template>
<script>import Vue from 'vue'import Home from './home.vue'import Welcome from './welcome.vue'export default Vue.extend({    components: {
        Home,
        Welcome
    }
})
</script>

在 Vue.js 中只有上述几个内置组件,使用时组件自身不产生 DOM 节点,在除了这几种内置组件之外的需求我们只能在循环块的外面加一个 <div> 去用 v-if 来判断循环块的显示隐藏,但是有时候父 <div> 可能会对内部块的样式带来不好的影响,我们还要在父 <div> 加上一些样式来消除该影响,同时也让 DOM 数层级会变得沉重冗余。但是有了 <block> 组件就很开心了,需要隐藏这个块,直接在外围加 <block> 就好了,渲染出来的 DOM 清爽干净。

属性的获取

快应用中也有 event,可以通过点击事件来传入相应的函数,通过打印 log,可以看一下具体包含什么:

<input id="test-link" class="link" data-detail="点击这里" @click="handleClick" type="button">去点餐</button>

打印出来的信息:

{    "type": "click", 
    "target": {        "ref": "5", 
        "type": "input", 
        "attr": {            "type": "button", 
            "dataDetail": "点击这里", 
            "id": "test-link"
        }, 
        "style": { }, 
        "event": [            "click"
        ]
    }, 
    "timestamp": 1522837358823}

通过 event 我们可以发现 target.attr.id 就是该元素的 id,在 event 中我们还可以看到定义的 data-detail 在 target.attr 中出现了。可见快应用中也可以自定义元素属性参数值。这样子就可以利用这个 target.attr 做一些事情了,比如我们想获取这个按钮上的文本,可以在 input 标签上加入 data-name="去点餐",那么就可以将其绑定到 attr 中,我们可以通过 event.target.attr.dataName 去获得这个按钮的名字。但是这并不是被快应用中所推荐,这样使用,控制台会有报错提醒:

ERROR: 组件 `input` 不支持属性 `data-detail`,
支持的属性有 [type, checked, name, value, placeholder, id, style, class, disabled, if, elif, else, for, tid, show]

Vue.js 支持通过 ref 属性来访问其它组件和 HTML 元素。并通过 this.$refs 可以得到组件或 HTML 元素的上下文。在大多数情况下,通过 this.$refs来访问其它组件的上下文同样也是不被 Vue.js 所推荐。

事件绑定

快应用中支持的事件有:

名称

参数

描述

click

-

组件被点击时触发

longpress

-

组件被长按时触发

blur

-

组件获得焦点时触发

appear

-

组件出现时触发

disappear

-

组件消失时触发

swipe 正式版本可用

组件上快速滑动后触发

使用的时候使用 on 或者简写 @ 绑定事件,例如 :

<a @click="handleClick">开始</a>

这种方式与 Vue.js 也很相似,不过 Vue.js 额外提供了事件修饰符,可以阻止一些事件的传播等,例如:

<!-- 阻止单击事件继续传播 --><a @click.stop="handleClick">开始</a>

事件监听

快应用的事件监听与 Vue.js 相似,都是使用 $on()$off $emit() 去监听,移除,触发事件,但是还是有一些区别。

监听原生组件事件

监听快应用的原生组件事件就用到了我们上面所说的提过的 event 的 target 来获取当前组件的信息, 例如用户选择取餐人的性别功能:

本文分享自微信公众号 - GitChat精品课(CSDN_Tech),作者:巧克力奶茶

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何在Windows中运行bash

    当微软宣布,将在Windows10上面支持bash时,所有的Unix命令行用户都为之雀跃了。上周三,微软发布了一个测试版本,开始支持了这项功能。 为了运行bas...

    CSDN技术头条
  • Redis 数据结构和对象系统,有这 12 张图就够了!

    Redis 是一个开源的 key-value 存储系统,它使用六种底层数据结构构建了包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象的对象系统。

    CSDN技术头条
  • MIT牛人梳理脉络详解宏伟现代数据体系

    在过去的一年中,我一直在数学的海洋中游荡,research进展不多,对于数学世界的阅历算是有了一些长进。 【为什么要深入数学的世界】 作为计算机的学生,我没有任...

    CSDN技术头条
  • 机器人“美食家”的食谱:惊喜与惊吓齐飞

    今年,美食界将迎来一位特殊的作家--IBM的超级计算机明星"沃森"(Watson)。《跟沃森大厨学烹饪》(Cognitive Cooking with Chef...

    机器人网
  • 猛犸系统

    10.猛犸也支持通过分布式Shell引擎支持传统的服务器模式。并且资源模型和传统的服务器模式同时并存,解决各自擅长的问题

    用户2936994
  • 将AI应用到供应链中的三个步骤

    导读:上一期了解了关于比特币相关的法律问题的相关介绍,今天我们来了解一下关于将AI应用到供应链中的相关内容(文末更多往期译文推荐) 现代全球供应链是由规模来定义...

    灯塔大数据
  • tensorflow学习笔记(四十三):使用 tfdbg 来 debug

    tensorflow学习笔记(四十三):使用 tfdbg 来 debug 由于 tensorflow 在训练的时候是在后台运行的,所以使用 python 的 d...

    ke1th
  • 人工智能将如何改变企业的决策?

    近年来,人工智能(AI)在科技领域取得了长足的进步。从挑选人们想去的餐厅开始,他们让Siri、谷歌助理、微软Cortana、AmazonAlexa等人工智能来控...

    liuxuewen
  • Cocos Creator常见问题汇总

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    bering
  • 如何为Kafka集群确定合适的分区数以及分区数过多带来的弊端

    通过之前的文章《Kafka分区分配策略》和《Kafka高性能揭秘》,我们了解到:Kafka高吞吐量的原因之一就是通过partition将topic中的消息保存到...

    大数据学习与分享

扫码关注云+社区

领取腾讯云代金券