本项目主要是为了熟悉快应用而练手的项目,该项目数据基于豆瓣api V2,简单的实现了电影、图书、音乐的预览功能。虽说快应用基于类似前端的html、css、js语法来编写代码的,但是使用时并没有那么好用,很多东西都没有得到支持。
前言
按照官方文档所说的,建议使用node v6.11.3版本,不要使用node 8.0以上版本,而我本地的node版本正是8.0以上的。所以就使用了nvm来管理node的版本,使用nvm切换node版本非常方便,关于nvm详情请自行google。我的代码就是在node 6.11.3上运行的,所以建议运行我代码也在node 6.11.3上。
简介
说到快应用,一般会拿来跟小程序做对比,就目前的api功能,debug能力,css属性支持等与小程序相比还是有一点距离。不过快应用是直接调用的系统api,所以流畅度还是蛮不错的。不管怎么说,毕竟快应用刚刚推出,希望它变得越来越好。
关于项目的搭建、运行、热加载、devtool调试,官方文档写的非常详细,而且也有很多人也写了入门demo和教程,我看了一下,大部分就是copy的官方文档。所以这里不做过多描述,多看官方文档吧。
通过这个项目,熟悉了一下快应用的基础组件使用,列表渲染,tab切换,api接口调用,页面传参,自定义组件的构建等。在使用中也遇到一些坑,再次记录下,我也是新手上路,也只用到部分功能,文章难免有不对的地方,欢迎大家指正。
说一下实现的功能:
本项目主要实现了电影、图书、音乐三个模块。每个模块都有三个类别,通过tab切换来查看不同类别。(比如图书有小说、历史、传记三个类别。)三个模块的ui展示都一样。主要使用了list实现了列表滚动,tab切换、refresh下拉刷新,数据懒加载等功能。每个模块都有一个详情页展示详情信息。首页有个测菜单栏,默认收起状态,通过点击菜单弹出菜单跳转到不同菜单页。菜单页主要有主页,主题页和关于页面,整个项目很简单。
下面就几个我认为重要的点说一下:
1、封装fetch数据请求
每个新的环境下我第一个封装的一般是网络请求。翻看了一下文档,支持async、await,果断引入,远离令人头疼的callback hell。文档说的很清楚,使用async,要引入babel-runtime/regenerator。所以在app.ux中首先引入。fetch通过async改造,同时结合豆瓣api V2对返回数据过滤后返回出来。并且封装了常用的get、post请求,并把封装的network对象暴露在全局,在所有文件中可以直接使用不用引入,详情请看代码。
2、封装自定义组件
我封装了一个评分组件和一个封面展示组件,和一个头部组件。这三个组件是纯渲染组件,没有什么逻辑的。同时做了一个列表组件,因为三个模块都是采用相同列表,列表组件通过传递的不同url来调用不同接口渲染列表。列表组件主要参考的官方文档,使用了数据懒加载,文档上写的很详细。同时也使用了tabs组件,refresh组件来实现横向滚动和下拉刷新。本来是准备进一步封装一个容器组件来完成这些功能的,但是看到自定义组件里slot只支持一个,不像vue那样可以命名slot。所以就放弃了做容器组件。
3、实现了一个抽屉效果的侧边栏菜单。
刚开始项目时就打算要实现一个模块来放个人信息,换肤的功能,本来打算模仿微信的,放在底部菜单,多一项叫做我的。由于我是网易云控,就打算模仿一下网易云,做个测边栏菜单,并且还有抽屉的滑入滑出效果,想看一下快应用上怎么实现动画。按照前端习惯,一上手就transition属性搞起,发现不支持,于是立马查看文档,只支持animation,并且属性要分开写。animation实现动画没有transition这么方便,打开和关闭要分别用不同的动画来实现,通过js修改class属性来实现不同的animation。但是有个蒙版,要在抽屉打开动画开始时打开,抽屉关闭动画结束后关闭。所以通过一个变量绑定style属性。在动画开始时立马显示。动画结束没法监听,只能通过定时器来实现。
4、换肤功能。
实现了一个简单的换肤功能,通过全局储存一个变量,通过改变变量来实现换肤功能。改变数据后,进入新页面,页面读取全局数据,加载页面就能正常切换皮肤,可是如果改变页面后当前页面的皮肤怎么变化呢?看到文档里有个$watch函数,可以监听属性变化,于是在需要实时切换肤色的页面定义一个变量,读取全局变量赋值给当前变量。再用$watch来监听该变量变化来实现实时换肤。但是当改变全局变量时,当前页面变量怎么会实时改变呢?对于一个原始类型的数据,当然不可能达到监听效果,这时只能通过对象来实现这一功能了。因为对象赋值会引用同一地址。所以可以实时监听数据变化。
需要注意的问题及坑:
1、调试相关
1、虽说快应用可以用谷歌的devtool的debug功能,但是其与谷歌debug差太多了。首先没有network模块,网络请求信息都看不到。其次在代码中的console.log输出的对象类型数据都会调用Object.prototype.toString方法转换成字符串。为此很头疼,每次获取的数据要调用JSON.stringify转换为json字符串输出,再将json转换成对象查看,很鸡肋的功能,有时一调用接口远程调试就闪退。
2、虽说是热更新,但是有时还是要手动重新启动项目才能达到预期效果,比如:添加了新文件。在manifest.json中修改不会热更新,要切换到其他页面保存。有时manifest.json中修改保存后也达不到预期效果,也要重启项目,比如头部栏样式。
2、基础组件相关
1、与小程序一样,快应用里的基本组件都是封装好的,只能用文档里提到的基本组件,而不是普通的html标签都能使用。每个组件的盒模型都是采用的box-sizing: border-box并且不准修改。这一点符合我们习惯,平时移动端项目也都是采用这种盒模型。
2、还有默认容器组件,比如我们用的比较多的div组件,其默认排列方式类似css中的行内块元素一样,而不同于html中div的块级元素。默认横向排列,要想纵向排列只能设置外层容器flex-direction为column。
3、对于自定义组件,在组件内最外层元素设置了class属性,在引入组件时,在组件上也使用class时,组件里的class属性会被覆盖,并不会叠加。
3、css相关
必须吐槽的是css的样式支持。太多的样式属性在里面都不支持,写起来一点也不爽。关于支持哪些css,可以看官方文档,写的很清楚。对于不支持的css在编译时会报红提示你不支持。
1、比如我在写样式写的正(。・∀・)ノ゙嗨时,突然发现没有达到预期效果,看了一下编译报错,不支持position: relative, absolute等属性,瞬间头疼,这不是很常用的样式,不支持?那快应用怎么实现这样效果了?翻看了一下文档,发现了一个容器组件stack组件,放在里面的子元素从上到下层级越来越高。这只实现了层级,怎么定位呢?当然是配合另外一个样式属性:translate同个这个属性可以上下左右移动来实现定位。上帝给你关上一扇门时,也会给你开另一扇窗,多看文档,骚年😳。
2、而且position支持fixed定位但是不支持z-index来调节层级,只能通过组件先后顺序来定层级。
3、普通容器不支持横向滚动,没有overflow的属性,只能通过tabs来hack。
4、动画不支持transition,只能通过animation来实现。
4、对于js部分
1、自定义组件引入后在上面加事件能正常监听,但是给监听函数传递参数,监听函数不能获取到。
2、基础组件的通用事件不知是否存在类似event这样的对象,只知道存在一个对象,但是打印为object类型,调用JSON.stringify函数会报错。
3、props不支持默认值,如果要默认值只能通过$watch来监听prop值的改变来自定义一个data属性。
4、绑定的通用事件会冒泡,但是没有提供阻止冒泡的方法,但是只会冒泡到最近一层包含监听该事件的元素上而不会继续向上冒泡。故可以通过绑定一个空函数来阻止事件冒泡。
5、在页面组件中可以通过this.$app和this.$app.$def这两个对象调用挂载到app.ux里的属性。但是注意:
app.ux中挂载的所有属性在this.$app.$def中都能获取到。但是只有方法属性会挂载到this.$app上。
6、refresh组件在使用时可以通过refreshing来切换当前状态,但是手动触发refresh事件时,refreshing并不会变为true,刷新结束后将其设置false并不能结束刷新状态。所以要同步设置refresh的状态,在refresh事件中将refreshing手动设置为true,待刷新结束后再将其设置为false,才会结束刷新状态。
7、引入组件中的资源引入路径是基于当前引入的组件。比如在组件中有个静态图片资源,我在组件里写死路径,当其他页面组件引用该组件时,会报找不到该资源的错误。必须将组件里的资源路径改为当前页面相对图片的路径,这显然有问题。不同页面引入资源路径当然有可能不同,只能通过props传递进去。
项目展示
前方多图预警。。。
电影图书
音乐
换肤
关于项目的任何问题,欢迎一起讨论!!!
放出项目地址:
项目地址:https://github.com/keenjaan/quick-app-douban
欢迎star #_#
网友评论