前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【独家】饿了么前端团队快应用背后研发实践

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

作者头像
CSDN技术头条
发布2018-07-30 11:32:32
1.7K0
发布2018-07-30 11:32:32
举报
文章被收录于专栏:CSDN技术头条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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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 一样通过脚手架工具快速生成一个项目模板:

代码语言:javascript
复制
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 进行引入,例如:

代码语言:javascript
复制
<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 中的场景,例如:‍‍

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

数据绑定

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

快应用:

代码语言:javascript
复制
<text>{{ title }}</text><richtext>{{ message }}</text>

Vue.js:

代码语言:javascript
复制
<div>{{ title }}</div><div v-html="message">

条件与列表渲染

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

代码语言:javascript
复制
<text if="{{conditionVar === 1}}">if: if条件</text>
<text elif="{{conditionVar === 2}}">elif: elif条件</text>
<text else>else: 其余</text>

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

代码语言:javascript
复制
<text show="{{showVar}}">show: 渲染但控制是否显示</text>

列表渲染:

代码语言:javascript
复制
 <div class="city" for="city in cities">
  <text>城市:{{city.name}}</text></div>

Vue.js 的条件渲染:

代码语言:javascript
复制
<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 指令:

代码语言:javascript
复制
<h1 v-show="ok">Hello!</h1>

列表渲染:

代码语言:javascript
复制
<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 属性上。

代码语言:javascript
复制
<template><component :is="isSignedIn ? 'home' : 'welcome'"></component></template>
代码语言:javascript
复制
<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,可以看一下具体包含什么:

代码语言:javascript
复制
<input id="test-link" class="link" data-detail="点击这里" @click="handleClick" type="button">去点餐</button>

打印出来的信息:

代码语言:javascript
复制
{    "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 去获得这个按钮的名字。但是这并不是被快应用中所推荐,这样使用,控制台会有报错提醒:

代码语言:javascript
复制
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 或者简写 @ 绑定事件,例如 :

代码语言:javascript
复制
<a @click="handleClick">开始</a>

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

代码语言:javascript
复制
<!-- 阻止单击事件继续传播 --><a @click.stop="handleClick">开始</a>

事件监听

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

监听原生组件事件

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GitChat精品课 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开发快应用的前提是拥有一台九大厂商品牌之一的安卓手机,然后注册快应用联盟账号,接着与该手机对应品牌的开发者账号进行绑定,然后照着快应用的开发文档进行开发,最后上传至快应用官网进行测试审核并分发。
  • 目前快应用还不能实现自动统一分发到各个平台去审核。如果想要在每个品牌的应用市场都上架自己的快应用,就需要每个平台的开发者账号都要去填写开发者信息,1-2工作日审核,然后再上架自己的快应用。
    • 模板定义
      • 自定义组件在模板中的引用
        • onInit
          • onReady
            • onShow
              • onHide
                • onDestroy
                  • 监听原生组件事件
                  相关产品与服务
                  内容识别
                  内容识别(Content Recognition,CR)是腾讯云数据万象推出的对图片内容进行识别、理解的服务,集成腾讯云 AI 的多种强大功能,对存储在腾讯云对象存储 COS 的数据提供图片标签、图片修复、二维码识别、语音识别、质量评估等增值服务。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档