请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
搜索

交流分享 [征文]全网最细致的快应用的踩坑与填坑之路

5
回复
704
查看
[复制链接]

1

主题

7

帖子

40

积分

QQ
 楼主| 2018-12-28 04:42:26 显示全部楼层 |阅读模式
本帖最后由 小明大白菜 于 2018-12-28 05:18 编辑

作者:小明
本文主要内容:
以下为本人在开发过程中遇到的问题与解决问题的方法,包括有:
  • 快应用常见问题。
  • CSS的box-shadow暂行替代方法。
  • CSS触摸反馈的实现与注意。
  • CSS动画遇到的问题。
  • CSS隐藏组件的动画实现。
  • 顶部栏titleBar的配置。
  • input组件的防止输入时标题被顶飞。
  • input的自动获取焦点例子。
  • 间接阻止冒泡事件。
  • 快应用编译出问题的解决方法。

前言:
快应用的官方文档已经算完善了,这里就不阐述如何去构建一个项目,还不知道如何去构建一个应用的可以看看官方的文章:

https://mp.weixin.qq.com/s/96y3g4UZGPC9_UZbGHuK5g

1、快应用常见问题

  • 快应用不像微信小程序,并不支持浮动float布局,也不支持grid布局,只支持flex布局。


  • 快应用里的CSS是间接用原生渲染实现的,所以并不支持web css全部属性,常见的不支持:box-shadow、overflow、letter-spacing、position的relative和absolut、transition、nth-child选择器、hover选择器

  • position只支持fixed属性。

  • 文字要用<text></text>包裹,在div层写文字默认不渲染,同样在div层设置字体color无效,与字体有关的css都要在text层设置。

  • 虽然支持border属性,但是你如果只是要一边border,这样写会不渲染:

  1. border-bottom: 5px solid #000000;
复制代码

  • 你应该这样写:
  1. border-bottom-width: 5px;
  2. border-bottom-style: solid;
  3. border-bottom-color: #000000;
复制代码


  • 快应用的px和网页的px不是同一个东西,快应用的px是这样定义的:
  1. 快应用750px = 网页100%width = 微信小程序750rpx = 网页100vw
复制代码


  • 快应用没有img这个标签,请使用image组件,虽然img会被渲染,但是不提倡,未来万一被废弃了呢。


  • 双括号{{}}内可以执行简单的js,可以使用三元表达式:
  1. <text>{{getText()}}</text>

  2. .....

  3. getText(){
  4.     return '我是小明'
  5. }
复制代码


  • 三元表达式特别有用,请务必学会,它是这样的形式:
  1. 条件 ? 成立执行我 : 不成立执行我
  2. {{ ok ? 'YES' : 'NO' }}
复制代码

  • 例子:
  1. <text>{{name == '小明'  ? '贼帅' :'一般般'}}</text>
  2. ........
  3. <script>
  4. export default{
  5.     data: {
  6.       name: '小明'    //是小明就会显示贼帅,不是就会显示一般般
  7.     }
  8. }
  9. </script>
复制代码



2、CSS的box-shadow暂行替代方法:

  • 设计中没有阴影就没有层次感,扁平看多了也会腻,但是快应用支持css阴影怎么办,小的这里有个傻招式:

  • 1、用Photoshop建一张长宽比比较大的透明图片,用渐变功能添加半透明黑色渐变,导出为png格式。

  • 2、在要用到阴影的div的边用image组件放上这张图片就行了,如果你多次用到某个地方,就弄成自定义组件调用。

阴影

阴影


  • 上面是我用的阴影png图,你可以用css的transfrom旋转它:
  1. .image{
  2.     transform: rotate(90deg); //旋转90度
  3. }
  4. .image{
  5.     transform: rotate(180deg); //旋转180度
  6. }
  7. .image{
  8.     transform: rotate(270deg); //旋转270度
  9. }
复制代码



3、CSS触摸反馈的实现与注意

  • 快应用和小程序都可以用:active伪类实现触摸反馈比如:
  1. <div class="btn"></div>

  2. .btn{
  3.     width: 200px;
  4.     height: 200px;
  5.     background-color: red;
  6. }
  7. .btn:active{
  8.     background-color: blue; <b>//div理论上按下时会变蓝,但实际不变蓝</b>
  9. }
复制代码


  • 注意:上面的div按下时并不会变蓝,div要触发active必须绑定一个click事件,比如:
  1. <template>
  2.     <div class="btn" onclick="doNotThing"></div>
  3. </template>

  4. <style>
  5. .btn{
  6.     width: 200px;
  7.     height: 200px;
  8.     background-color: red;
  9. }
  10. .btn:active{
  11.     background-color: blue;<b> //这次,div按下就会变蓝了</b>
  12. }
  13. </style>

  14. <script>
  15. export default{
  16.     data:{
  17.    
  18.     },
  19.     doNotThing(){
  20.    
  21.     }
  22. }
  23. </script>
复制代码


  • 另外,input的button不用绑事件就能触发这个:active,例如:
  1. <template>
  2.     <input type="button" class="btn" value="按钮"/>
  3. </template>

  4. <style>
  5. .btn{
  6.     width: 200px;
  7.     height: 100px;
  8.     background-color: red;
  9. }
  10. .btn:active{
  11.     background-color: blue; //button按下就会变蓝
  12. }
  13. </style>
复制代码



4、CSS动画遇到的问题

  • css动画不能行间绑定,像这样是失效的:
  1. <template>
  2.     <div style="animation-name:{{animeName}};animation-duration:{{animeDuration}};animation-iteration-count: infinite;animation-timing-function: linear;" class="box">
  3.         <text>动画</text>
  4.     </div>
  5. </template>

  6. <style>
  7. .box{
  8.     width: 200px;
  9.     height: 200px;
  10.     background-color: blue;
  11. }
  12. @keyframes myAnime{
  13.     from{
  14.         opacity: 0;
  15.     }
  16.     to{
  17.         opacity: 1;
  18.    }
  19. }
  20. </style>

  21. <script>
  22. export default {
  23.     data: {
  24.         animeName: 'myAnime',
  25.         animeDuration: '2s'
  26.     }
  27. }
  28. </script>
复制代码


  • 替代方法:控制不了anime,但是可以控制class名字嘛,整多几个class,把anime分别绑定到class,在动态控制class名字:
  1. <div class="{{anime}}">
  2.     <text>动画</text>
  3. </div>

  4. ......style.....

  5. .anime1{
  6.   .....
  7. }
  8. .anime2{
  9.   .....
  10. }

  11. ...script.....
  12. export default{
  13.     data:{
  14.         anime: 'anime1'  //此时执行动画1
  15.     }
  16. }
复制代码



5、CSS隐藏组件的动画实现

  • 因为出现动画比较容易实现,这里就不详细说了,这里说说怎么做消失动画。

  • 一般我们隐藏组件是用if="{{false}}"或show="{{false}}"来实现的,这样即使动态绑定anime的消失动画class,也来不及执行动画,组件就提前隐藏了。

  • 所以,要换个思路,在隐藏组件时,延迟隐藏,延迟的时间和动画的时间相同。这样就能保证动画完全执行完后,组件才消失。举个淡出的例子:
  1. <template>
  2.     <div class="box {{isGoingClose ? closeAnime : ''}}" onclick="closeDiv">
  3.         <text>动画</text>
  4.     </div>
  5. </template>


  6. <style>
  7. .box{
  8.     width: 200px;
  9.     height: 200px;
  10.     background-color: blue;
  11. }
  12. .closeAnime{
  13.     animation-name: close;
  14.     animation-duration: 2s;
  15.     animation-iteration-count: 1;
  16.     animation-timing-function: ease-out;
  17. }
  18. @keyframes close{
  19.     from{
  20.         opacity: 1;
  21.     }
  22.     to{
  23.         opacity: 0;
  24.     }
  25. }
  26. </style>


  27. <script>
  28. export default {
  29.     data: {
  30.         isGoingClose: false,  //用于判定是否点击了div
  31.         timer: null //用于存放定时器
  32.     },
  33.     closeDiv(){
  34.         this.isGoingClose = true;
  35.         if(!!this.timer){
  36.             clearTimeout(this.timer);
  37.         }
  38.         this.timer = setTimeout(()=>{
  39.             this.isGoingClose = false;
  40.         },2000); //这里的时间要和动画时间保持一致
  41.     }
  42. }
  43. </script>
复制代码


这样,点击div就能淡出了。



6、顶部栏titleBar的配置

  • 专门抽这块出来是因为大家经常会用到。这里可以分三个配置方式。

  • 1、在项目下的manifest.json文件里全局配置,一次性配全部页面,优点:省事,缺点:不能差异性配置。

  • 2、在项目下的manifest.json文件里全局配置,单个页面配置,优点:方便管理,缺点:静态配置、不能动态变。

  • 3、在项目的具体page页,在页面初始化函数里面配置,优点:可以动态修改titleBar,缺点:管理起来不直观。

  • 1、manifest.json一次性配值所有页面的titleBar:
  1. //在manifest.json里用ctrl+f搜索display,然后你会看到

  2. "display": {
  3.     "backgroundColor": "#ffffff", //所有页面的初始背景颜色
  4.     "fullScreen": false, //是否全屏显示,是的话会隐藏状态栏
  5.     "titleBar": true, //是否显示titleBar
  6.     "titleBarBackgroundColor": "#eeeeee", //配置titleBar的背景色,注意这里的颜色会同时配置到全部页面的状态栏颜色。
  7.     "titleBarTextColor": "#000000", //配置titleBar的文字颜色
  8.     "menu": false, //是否在titleBar右边显示三个点作为菜单
  9.     "pages": { //这里开始,是单个页面的配置了。
  10.         ......
  11.     }
  12. }
复制代码



  • 2、manifest.json一个页面一个页面地配置titleBar:
  1. //在manifest.json里用ctrl+f搜索display,然后你会看到
  2. //比如说我有pageA和pageB,我要pageA开titleBar,pageB不开titleBar
  3. "display":{
  4.     ........
  5.     "pages": {
  6.         "pageA": {
  7.             "backgroundColor": "#000000", //设置pageA的初始背景颜色为黑色
  8.             "fullScreen": false, //设置pageA隐藏状态栏
  9.             "titleBar": true, //设置pageA显示titleBar
  10.             "titleBarBackgroundColor": "#0000ff", //设置pageA的titleBar的背景为蓝色
  11.             "titleBarTextColor": "#ffffff", //设置pageA的titleBar的文字颜色为白色
  12.             "menu": false //设置pageA的titleBar不显示菜单
  13.         },
  14.         "pageB": {
  15.             "backgroundColor": "#ffffff", //设置pageB的初始背景颜色为黑色
  16.             "fullScreen": true, //设置pageB不隐藏状态栏
  17.             "titleBar": false, //设置pageB不显示titleBar
  18.             "menu": false //设置pageB的titleBar不显示菜单
  19.         }
  20.     }
  21. }
复制代码






  • 3、在具体的某个页面动态修改titleBar:
  1. //比如我让页面加载完时修改titleBar样式

  2. <script>
  3. export default{
  4.     data:{
  5.    
  6.     },
  7.     onInit(){ //页面初始化完会调用这个函数
  8.         this.$page.setTitleBar({
  9.             text: '小明的标题', //设置本页titleBar标题
  10.             textColor: '#ff0000', //设置本页titleBar标题文字颜色
  11.             backgroundColor: '#00ff00',//设置本页titleBar标题背景颜色
  12.             backgroundOpacity: 0.5,//设置本页titleBar标题背景颜色透明度,0为全透明,1为不透明。
  13.             menu: true //设置本页的titleBar是否启用菜单。
  14.         })
  15.     }
  16. }
  17. </script>
复制代码



  • 假如你闲的慌,对同一个页面:用方法一设置了标题文字颜色为红色,用方法二设置了标题文字颜色为绿色,用方法三设置了标题文字颜色为蓝色,那么最终那个页面标题文字会显示那个颜色呢?

  • 答案是蓝色,因为内部渲染优先级方法三 > 方法二 > 方法一



7、input组件的防止输入时标题被顶飞。

  • 在用input组件时,我经常会遇到标题栏会被顶飞到和状态栏重合,对强迫症来说不是一件什么好事,不过1030版本已经可以解决这个问题。
  1. //在manifest.json里用ctrl+f搜索display,然后你会看到

  2. "display": {
  3.     "fullScreen": false, //设置不全屏,下面这句防顶飞才生效
  4.     "windowSoftInputMode: "adjustResize" //防顶飞
  5.     "pages":{
  6.         ......
  7.     }
  8. }
复制代码

  • windowSoftInputMode有两个值可选:adjustPan(顶飞) | adjustResize(不顶飞),默认顶飞,如果设置了全屏,则不顶飞失效。



8、input的自动获取焦点例子

  • 一开始我以为快应用的input自动获取焦点为focus="true",后来发现并不行,我试了以下几种方法都不行,错误示例:
  1. <input type='text' focus/>

  2. <input type='text' focus="true"/>

  3. <input type='text' focus="{{true}}"/>
复制代码


  • 后来研究了一下文档,发现是这样用的,希望大家别踩我这个坑:
  1. <input type='text' id="my-input"/>

  2. ......

  3. <script>
  4. export default{
  5.     data:{},
  6.     onReady(){
  7.         this.$element("my-input").focus({
  8.             focus: true
  9.         })
  10.     }
  11. }
  12. </script>
复制代码

  • 注意:this.$element()里传的是id名称而不是class类名,不要在onInit()里使用这个方法,还没开始渲染,获取不了节点,会报错。onReady()里可以使用,因为此时节点已经渲染完。



9、间接阻止冒泡事件。

  • 官方貌似没提供阻止冒泡事件,因为快应用是默认阻止冒泡的,但是我在某次封装组件在调用时,事件神奇的冒泡了。我请教了群里的大神,想到了一种貌似可以阻止冒泡的方法。
  1. <div class="boxB" onclick="eventB">
  2.     <div class="boxA" onclick="eventA"></div>
  3. </div>

  4. ......

  5. <script>
  6. export default{
  7.     data:{
  8.         isStop: false
  9.     },
  10.     eventA(){
  11.         this.isStop = true;
  12.         console.log("执行了eventA");
  13.     },
  14.     eventB(){
  15.         if(this.isStop == true){
  16.             this.isStop == false;
  17.             return;
  18.         }
  19.         console.log("执行了eventB");
  20.     }
  21. }
  22. </script>
复制代码





10、快应用编译出问题的解决方法

  • 常见的编译问题:代码错误(这个就不说了,自己查错误日志然后修bug)、编译失败:找不到node module,可以尝试打开调试板,点击终端,输入npm  install,如图:

捕获1.PNG


  • 如果还是编译不成功就把项目下的node_modules删了,再npm install一次,通常这样就能解决大部分编译失败问题。

捕获2.PNG


  • 注意:npm install的过程会有点慢,因为依赖包服务器在国外,想快的话就xx(和谐),或者用淘宝镜像cnpm,使用教程:https://npm.taobao.org/


  • 如果你试了上面的方法都不行,还是编译失败,可能你遇到了我这个问题。有一次因为要安装deepin,我就把d盘空了出来,快应用开发工具也从d盘移到了f盘,于是问题出现了,不管我怎么编译都不成功,我重复试了上面的方法,还重装了快应用开发工具,都是不行,编译失败。

  • 后来发现要改一下项目配置:
  1. 第一步:在快应用开发工具的安装目录找到\resources\app\extensions\hap-debugger\toolkit,你会看到有一个叫hap-toolkit.tgz的文件,我们需要它的路径

  2. 第二步:在项目根目录找到package.json,打开,ctrl+f搜索hap-toolkit,你会看到

  3. "hap-toolkit": "一条长长的路径"

  4. 把刚才我们找的这个文件的路径替换原来的,保存,记得要用\\而不是\,举个例子,我在F盘的Quickapp下面装了快应用开发工具,那我的hap-toolkit.tgz文件路径应该是
  5. F:\Quickapp\resources\app\extensions\hap-debugger\toolkit\hap-toolkit.tgz

  6. 那我应该这样写:
  7. "hap-toolkit": "f:\\Quickapp\\resources\\app\\extensions\\hap-debugger\\toolkit\\hap-toolkit.tgz"

  8. 写完ctrl+c保存,然后删除项目根目录的node_modules文件夹,然后在调试工具的终端输入npm install,完了你就会惊喜的发现项目又可以跑了。
复制代码


以上基于1030版本,个人测试手机华为honnor 5c,不排除这些问题未来会被修复或手机不同从而导致测试结果不同。所以自己动手实践才是真理。

我是小明,一名渣渣大学生,写这篇文章花了我很多个小时,希望能让读着这篇文章的你少踩几个坑,少走点弯路。最后,祝快应用越来越好。





阴影

阴影
回复

使用道具 举报

1

主题

3

帖子

20

积分

2018-12-28 11:22:00 显示全部楼层
这个厉害了
回复

使用道具 举报

1

主题

8

帖子

45

积分

2018-12-28 12:12:46 显示全部楼层
膜拜大神啊!
回复

使用道具 举报

6

主题

53

帖子

295

积分

2019-1-2 20:57:24 显示全部楼层
太厉害了大神。 666 。 都是开发的重点。
回复

使用道具 举报

1

主题

3

帖子

20

积分

2019-1-5 21:41:41 显示全部楼层
666
回复

使用道具 举报

1

主题

3

帖子

20

积分

2019-2-15 14:06:29 显示全部楼层
火钳刘明
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册