4

系列文章的目录在 ? 这里

在配置完开发环境之后,就可以开始写应用了。在写应用之前,肯定会先划分好页面,一个一个独立着写的。

不过,首先要明确的是,使用 Weex 写出来的是原生应用,页面的概念还和 Web 上一样吗?

Weex 里“页面”的概念

写的有些乱,与下边内容关系不太,不理解可以忽略。

Weex 的实例在 Web 上是和“浏览器页签”的概念相对应的,通常一个 Weex 实例就是一个“页面”。

在 Web 上,只要没有新开页签,网页中的各种跳转,都是记录在 History 对象中的,对于 Weex 而言,这些都相当与在一个“页面”之内。在 Native 上,页面的跳转是记录在 Navigator 中的,内部也有一个栈来存储跳转记录,可以 pushpop

要想在原生页面之间(Weex 多实例之间)跳转,可以使用 navigator 模块,也可以看看 weex-router

想深入理解这方面的概念,还需要了解一些 Native 开发的知识。原生开发里边,页面是个比较上层的概念,可以来回切换和销毁,在背后还有生命周期更长程序在运行,Weex Runtime 就运行在这一层里,多个 Weex 的实例会共用一个 Runtime。

因为 vue-router 的设计和实现都是在同一个页面内的,是 SPA 概念里的产物。其实前端路由也是基于 SPA 产生的概念,在 Weex 或者原生应用这种多页跳转的场景里可能并不合适,慎重使用。虽然 weex-hackernews 项目里用了 vue-router ,但是依然在同一个 Weex 实例中。相关话题我在 《使用 vue-router》这篇文章里详细再说。

编写入口文件

weex-hackernews 为例,看 webpack.config.js 中的配置,src/entry.js 就是入口文件。项目代码中因为用了 Vuex 和 vue-router,入口文件还有点长,其实只需要引入口组件,配置挂载点,然后初始化 Vue 实例就行了。

import Vue from 'vue'
import App from './App.vue'

// 将 App 组件挂载到 #root 之上,生成的 DOM 节点会替换 #root 标签
App.el = '#root'

// 创建 Vue 实例
new Vue(App)

这还要求你在 Web 入口 HTML 文件里手动写上 #root 的标签:

<div id="root"></div>

至于 Android 和 iOS 平台,只要指定了 el 属性即可,属性值就无所谓了,Weex 会默认将其挂载到容器根视图中(可由 Native 端配置)。

使用单文件组件

在配置好入口文件之后,就可以开始写组件了,推荐写单文件组件,也就是 .vue 文件。语法就不再重复介绍,官方文档中写得很详细,能支持 ES6+,甚至可以配置 TypeScript 、Sass 、Stylus 、PostCSS 、Jade 等语法。

vue-single-file-component

需要注意的是,针对 Web 平台,依然使用 Webpack + vue-loader 的方式编译 .vue 文件,但是针对 Android 和 iOS 平台,你必须使用 Webpack + weex-loader 才可以。也就是说,针对 Web 和 Native 平台要分别生成两份不同的 js bundle,具体的配置参考 webpack.config.js

只使用 Vue Runtime 的功能

Weex 已经将 Vue Runtime 的代码整合进了 SDK 中,Vue 中支持的语法特性也能用在 Weex 中。注意,是 Vue Runtime (运行时构建)。如果你下载过 Vue 2.0 对外发布的版本,应该能发现除了区分产品版和开发版,既区分 “Standalone” 版本和 “Runtime-only” 版本,具体的差异可以看官方安装指南(其实有些名词不太好翻译,看英文原版文档或许能理解得更准确一些)。

简单来说,Vue 在 Weex 中使用的是“预编译”模式,只保留了运行时,不支持实时编译模板。简单来说,就是不支持下边几个特性:

  • 定义组件时不支持使用 template 属性。

  • 不支持使用 x-templates

  • 不支持使用 Vue.compile

如何做到跨平台?

写代码的过程和写其他 Vue 2.0 项目是一样的,没什么可说的。但是既然说了是写原生应用,就要注意跨平台的问题,虽然 Weex 抹平了很多差异,但是平台差异是客观存在的。Web 和 Android 和 iOS 毕竟都不相同,想写跨平台的应用,了解平台差异还是很有必要的。

了解平台差异

推荐阅读官方文档:

大概摘录一下是这样的:

  • Weex 环境中没有 DOM

    • 不支持 DOM 操作,原生平台没有 DOM 概念。

    • 并不支持 Web 中所有的事件类型,详情请参考《通用事件》

    • 不区分事件的捕获阶段和冒泡阶段,相当于 DOM 0 级事件。

  • Weex 环境中没有 BOM

    • 没有 window 、screen 对象,可以通过 WXEnvironment 获取设备环境信息。

    • 没有 document 对象,没有选择器方法。

    • 没有 history 、location 、navigator 对象,有 navigator 模块

  • 能够调用移动设备原生 API

    • 可以通过模块调用设备原生 API,如 clipboard 、 navigator 、storage 等。

使用通用组件

为了保证三端可用,不能使用浏览器提供的标签,只能用 Weex 提供的标签(组件)。如果你写了 <figure> 或者 <menu> 这类组件,在 Web 端可以看到效果,但是在客户端上渲染效果是不确定的。而且,客户端上没有 SEO 和语义化的需求,HTML5 中的大多数标签都可以通过别名实现(参考 weex-component-alias)。

具体组件的使用方法参考官方文档。

使用通用样式

CSS 的属性特别多,写法也特别多,能力很强大,也有很多坑。一方面新标准在不断的提出,像 CSS Grid 和 Houdini 这些概念也逐渐受到关注;另一方面旧标准是很难再废除的,新旧语法总能摩擦出各种奇葩的行为,CSS 也是容易滋生“奇技淫巧”的地方,也有各种关于“最佳实践”的话题,很多人乐于此道。浏览器内部为了处理这些边界情况肯定用了大量“特殊技巧”。

然而在实际使用中,绝大多数的网页只用了其中很少一部分属性(参考 Global CSS property usage)。Weex 是由 Native 平台解析的样式,Android 和 iOS 本身并不支持 CSS ,所有解析都是原生渲染器实时计算的,所以必然要再性能和可用性之间做平衡。既然不能支持、也不打算支持所有 CSS 特性,那就必然要分清主次,优先支持常用样式。

Weex 对 CSS 样式的支持情况,可以参考这篇文档。简单概括下边几点:

  • 支持基本的盒模型。

  • 支持 position 定位布局。

  • 支持使用 flexbox 布局。

  • 使用限制

    • 只支持单个类名选择器,不支持关系选择器,也不支持属性选择器。

    • 默认是组件级别的作用域,没有全局样式。

    • 不支持样式继承(因为有作用域隔离)。

    • 考虑到样式的数据绑定,样式属性暂不支持简写。


Hanks10100
1.5k 声望372 粉丝