微信号:csdnbigdata

介绍:CSDN分享Hadoop、Spark、NoSQL/NewSQL、HBase、Impala、内存计算、流计算、机器学习和智能算法等相关大数据观点,提供云计算和大数据技术、平台、实践和产业信息等服务.

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

2018-04-14 22:12 巧克力奶茶



作者说:


饿了么是一年前开始参与内测尝试开发快应用的,看着快应用平台一步一步的走过来,发展的越来越好。目前来说快应用开发条件已经比较完善,本次分享,为大家介绍前端开发人员眼中快应用的开发与使用 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. a p p . 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 来获取当前组件的信息, 例如用户选择取餐人的性别功能:



阅读全文请扫描

下方二维码,

还可以加入读者圈与作者聊天~:




 
CSDN大数据 更多文章 别再说「同龄人」抛弃你,其实根本没人搭理你 Lambda架构已死,去ETL化的IOTA才是未来 聊下大厂都在用的“用户拉新”手段:一级分销 技术人不会学习,35岁必然要焦虑 【剧透】阿里数据库已备下双·11神器:新一代X-DB
猜您喜欢 【公开课】PS高级图片合成案例及网页登录界面设计 白话Reactor模型 读懂营销:新媒体人最宝贵的软实力 解放程序猿(媛)的双手---iOS UI自动化测试 云计算或在三个方向颠覆安防行业