TAT.vorshen QQ 日迹 Omi 实战开发,从 0 到 1
In Web开发 on 2017年07月14日 by view: 2,176
0

相信大家对 Omi 应该都不陌生了,如果还有不了解的同学先看看这里。了解并使用 Omi 之后你会发现真的回不去了~~~

精通 Omi 框架

先简单说一下吧,Omi 就是一个可以快速开发项目的组件化框架,和 vue/react 一样为了节省生产力的。想了解 Omi 和 vue 还有 react 区别的,上面文档有讲解,或者加入群 256426170,可以面对面咨询 Omi 作者 dnt。我这篇文章将使用 Omi 从 0 到 1 来完成一个移动端的项目,让大家了解 Omi 开发的方便快捷。



开发准备:

这次我们挑选了一个日迹发现页来作为例子开发,如果有用手机QQ的同学,应该有知道“日迹”这个项目,这次我们就挑选了一个日迹的一个发现页,入口在手机QQ -> 动态 -> 日迹 -> 右上角发现
发现页如下

开发一个移动端页面和 PC 上开发是一样的,首先要分析页面划分模块,发现页很简单,可以看成一个列表,然后里面每一块是一个 item
如果不用组件化的话,ul+li 是不是就可以上手干了~但我们要告别原始社会的开发方式,采用 Omi 框架进行开发,下面就正式开始开发~

开发过程:


1/ 脚手架

开发一个项目 (一个页面也是一个项目),首先我们需要脚手架,脚手架可以从历史项目中复制过来,也可以自己重新搭建。使用 Omi 的话就方便很多啦,我们只需要下面两步

然后脚手架就 OK 了,下面简单的看一下脚手架,了解一下项目结构

下面那些.babelrc/.eslintrc/package.json 等就不说了
先看目录,config 是配置目录,里面有基础配置和项目配置,一般我们不需要修改
tools 里面是构建相关,webpack.base.js 是基础配置,然后测试环境和生产环境的区分就靠 script.js 了

src 是开发的目录,也是我们代码所在地,打开 src 再看一下

应该还是很好理解的,page 是页面,这里面每个目录就意味着有一个页面。页面的入口是目录下的 main

component 是组件,组件也是以文件夹为粒度来的,里面一定有一个 js 文件,然后组件相关的资源文件,样式文件也都放在 js 的同一目录下,比如这样

组件的图片/样式和 js 都有了,那外面的 css/img/js 呢?是一些全局资源和公共方法等,这样一来复用就极为方便了。

2/ 正式开发

首先我们引入一下 rem 统一的 js 代码,现在来说用 rem 还是比 px 方便很多的,代码如下:

这样我们就将不同屏幕下的 rem 与 px 转换统一了,视觉稿上面的 px 单位除以 37.5 就可以了,这一步也可以在构建的时候做

接下来我们考虑到项目是一个长列表,说到长列表就肯定离不开滚动,说到滚动就想到了安卓下局部滚动会很卡。那么这里可以用全局滚动搞定么?可以的,因为页面本身不复杂。
那么复杂的情景下,必须是局部滚动的场景怎么办呢?AlloyTouch 欢迎你~解决各类滚动问题,而且有 Omi 插件的无缝支持版本。

使用 omi-touch

准备工作都考虑完善之后我们就开始写第一个组件了!第一个组件可以看成是整个列表的一个包裹盒,盒子里面不仅有 list,还有按钮和一些其他的玩意
先上一下代码

超级简单明了,constructor 是组件的构造函数,也是生命周期的开始,因为我们包裹盒的组件一直存在,所以没有用上其他生命周期的方法。但 Omi 对组件生命周期的控制可是非常强大的,如下图

接着是 style 和 render,这里是用模版字符串写 css 和 html,很方便,但如果觉得麻烦也可以用文件的形式,后面会说

下面三个是啥呢?是自己模拟的 tap,因为移动端下 onclick 有 300ms 的延迟,所以我们用的点击都是模拟的。tap 用语言描述就是一次点击,我们要保证 touchend 时候手指的位置不能距离 touchstart 的位置太远,而且 end 和 start 期间不能触发 touchmove,这也就是自己实现 tap 的核心了。

如果有 zepto 的话本身可以用 ontap 事件,不必自己去写,但是我这里没有引入 zepto,而且 zepto 本身是 jquery 类似的写法,和框架开发还是比较背驰的。那么我们就只能自己写这么多代码去模拟么??
当然不是!因为我们有 alloyfinger-omi 版,我们只需要这样

安装:

使用:

使用 omi-finger

就可以了!alloytouch 里面的手势操作 omi-finger 都可以用,而且用起来也超级方便!

这样就可以了,这就是 Omi 插件体系的好处,顺带一提 alloytouch 也可以像 finger 这样使用~

这样最外层的包裹组件就已经 ok 了,我们来看核心的 list 组件。
再上代码

首先可以看到和 main 不同的是,这里我们就把 css 给抽离成文件的形式了,纯看个人喜好。不过有一些需要注意的地方:
1. 全局 css 只需要在文件中 import 就可以了
2. 局部 css 或者 less 文件名必须以_开头,loader 会针对进行操作,就像上面的代码一样
3. html 抽离成文件的话需要用模版引擎的方式,上面代码用的是 ES6 模版字符串,这样的话是无法抽离成文件的。

omi.js 默认的模版引擎是 soda,如果还有喜欢 ejs、mustache 语法的同学,虽然 omi.js 本身没有内置该写法,但是用 omi.mustache.js 却将其默认为内置模版引擎
具体的情况如下:

  • omi.js 使用 sodajs 为内置指令系统
  • omi.art.js 使用 art-template 为内置模版引擎
  • omi.lite.js 不包含任何模板引擎
  • omi.mustache.js 使用 mustache.js 为内置模版引擎

接下来重点讲的就是其中的循环生成子组件部分
循环渲染有多种方式,刚刚代码部分用的是 ES6 执行 map,然后获取到数组中每一个元素,渲染
我们也可以使用 omi 中内置的 soda 模版的指令方式,如下代码也可以实现同样的功能

我们在 add 方法中进行数据的处理,这里组件的 data 下面有两个数组,分别是左右两边的。注意这里 add 方法最后有调用一个 update() 方法,omi 本身没有双向绑定,将更新的操作交给了开发者。当然如果希望双向绑定的话也可以引入 Mobx 之类的第三方库。

list 组件里面有一个 item 组件,这个 item 组件就是最后一个啦,它需要从 list 中接受到自己的数据,然后将数据给展示出来
数据传递的方式有很多种,简单的说一下

  • on-* 代表传递父组件向子组件注入的回调函数,比 on-page-change="pageChangeHandler"
  • data-* 代表直接传递字符串
  • :data-* 代表传递 javascript 表达式,比如 data-num="1" 代表传递数字 1 而非字符串,data-num="1+1"可以传递 2。
  • ::data-* 代表传递父组件的属性,比如上面的::data-items="data.items"就代表传递 this.data.items 给子组件
  • data 代表传递父组件的属性,比如 data="user"代表传递 this.user 给子组件
  • :data 代表传递 javascript 表达式,比如 data="{ name : 'dntzhang' , age : 18 }"代表传递 { name : 'dntzhang' , age : 18 } 给子组件
  • group-data 代表传递父组件的数组一一映射到子组件

我们采用的是第 x 种,然后 item 中就是简单的展示啦

3/ 构建相关

开发过程中我们只需要 npm start,然后就可以专注的撸代码了
可以用默认的 localhost:9000 端口进行访问
也可以修改 config 目录下的 config.js 文件,用路由的方式访问,比如我这样

当然我这里是有配置代理的,将 xxx.qq.com/mobile 指向了本地的 localhost:9000
当你开发完成后,只需要运行

生产环境的代码就已经搞定了~接下来就是部署、提测...

结语

文章一些 cgi、util 相关的代码就省略掉了,主要目的是讲解 Omi 的开发。虽然是一个很小的页面,不过可以看出来用 omi+omi-cli 开发还是很简单的哈!Omi 的能力当然不止这一点点,我这篇文章只是抛砖引玉,大家想解放生产力的话, 快来使用 Omi 吧~~

在线体验地址,请使用手机 QQ 扫描下方二维码

github 地址:

有问题的话可以留言大家一起交流~

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2017/07/12859/

发表评论