前端开发_快应用开发

目录

      • 快应用官网
      • 真机调试
      • 组件
        • 组件引入
        • 组件嵌套问题
        • 组件通信
        • 快应用组件
          • tab组件
          • list组件
          • web组件
            • 语法
            • 路由跳转时schema 是 http/https
        • web页面与快应用通信
          • 快应用接收/发送消息
          • 网页接收发送消息
          • 通信流程
          • 通信注意事项
        • 第三方组件库
      • css 样式问题
        • [1]选择器
        • [2]盒模型
        • [3]样式布局-弹性布局
        • [4-1]样式切换 - 类名的动态切换
        • [4-2] 样式切换 - 行内样式动态切换
        • [5]background
        • [6]overflow
        • [7]border-radius
        • [8]盒子阴影
        • [9] 单位
        • [10] 定位
      • 系统接口
        • [1] 检查某app是否在手机上安装
        • [2] 下载应用
        • [3] 检查当前是否有桌面应用
        • [4] 添加桌面应用
        • [5]数据存储
        • [6]弹框
        • [7] 接口
        • [8]获取设备信息
        • [9] 路由传参
      • 数据
        • [1] 计算属性
      • 埋点
      • 公共对象
        • global对象
        • $app
          • 退出快应用
        • $element
          • 获取指定element元素
      • manifest配置文件
        • config - 系统配置信息
          • designWidth - 项目配置基准宽度
          • data - 全局数据对象
        • router - 配置路由
          • entry
          • pages

  • 点击其他地方关闭弹框
  • 全局变量 blobal
  • Scheme协议

快应用官网

快应用官网

真机调试

在开发开应用时,需要真机调试。

很多UI在模拟器上显示正确但是在真机上显示错乱 – 因此在调试时需要以真机为主。

  • 方法1: 远程预览

    直接微信扫(远程预览)二维码进入调试模式

  • 方法2: 使用调试器调试

  • 方法2的优势是在运行的时候若是逻辑错误可以看到运行报错,有助于我们解决问题。
    比如说我在逻辑代码中使用了window对象进行事件监听,在远程预览时功能不能正常运行,但是定位不到问题的原因,使用调试器进行调试可以看到错误,能快速定位问题---- 没有window对象。

组件

组件引入

前端开发_快应用开发_第1张图片

组件嵌套问题
  • [1] 文本必须包裹在 text组件或span组件中,否则不显示;
  • [2] span必须作为text/a/span组件的子组件,否则不显示;
组件通信
快应用组件
tab组件

tab组件中的tab-content中的数据不支持动态增加或减少!如果要减少页面,需要先销毁掉,重新用新的实例展示数据 ===> 快应用提供了if命令,if为false时,页面不显示,并且dom节点也会移除。

<tab if='bol'>
  <tab-bar>tab-bar>
  <tab-content>tab-content>
tab>

但是这样将会导致每次切换tab数据加载时 tab-bar的滚动条都会滚动到初始位置(最左边),而且数据加载中tab-bar数据也会暂时消失 ===> 用户体验感不好;
我们可以只使用tab-bar来显示滚动条的tab数据,底部content内容使用普通组件div进行显示!

list组件

list-item — type属性必填 不然list不会滚动

web组件

若是某些不是很重要的页面,可以将web页面嵌套进快应用中 ===> 打开会比原生慢一点~

语法
<web src='http://baidu.com'>web>
路由跳转时schema 是 http/https

若是路由跳转的uri的schema是 http/https时,改uri默认会使用内置的web组件打开
在这里插入图片描述

web页面与快应用通信

快应用是允许快应用页面与文本页面通信的。

快应用接收/发送消息

前端开发_快应用开发_第2张图片
在这里插入图片描述

网页接收发送消息

当网页被嵌入快应用时,默认会向该网页的windows中添加两个方法
在这里插入图片描述
注意: 该方法只有在嵌套的web页面且在快应用ide中浏览时可以使用,否则这两个方法将不存在!

通信流程
通信注意事项
  • 必须添加 trustedurl ,只有互相信任的页面路径才会允许通信,在默认情况下会添加web组件的src属性到trustedurl中;若是URL永远不变,则可以省略,若是路径携带参数或url不是固定值,则必须添加trustedurl;
  • 向网页发送请求
    this.$element('web').postMessage({
      message: messageString,
      success: function(){},
      fail: function(){}
    })
    
    注意点:
    • [1] message必须为String类型,若是传递其他数据类型如对象,在真机环境会报错
      java.lang.ClassCastException: org.json.JSONObject cannot be cast   to java.lang.String
      at org.hapjs.widgets.Web.f(SourceFile:535)
      at org.hapjs.widgets.Web.invokeMethod(SourceFile:681)
      at org.hapjs.render.b.a.a(SourceFile:30)
      at org.hapjs.render.RootView.applyAction(SourceFile:1134)
      at org.hapjs.render.RootView.applyActions(SourceFile:1120)
      at org.hapjs.render.RootView.a(SourceFile:1105)
      at org.hapjs.render.RootView.e(SourceFile:1088)
      at org.hapjs.render.RootView$a.handleMessage(SourceFile:365)
      at android.os.Handler.dispatchMessage(Handler.java:117)
      at android.os.Looper.loopOnce(Looper.java:205)
      at android.os.Looper.loop(Looper.java:293)
      at android.app.ActivityThread.main(ActivityThread.java:9596)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1204)
      
      若是想发送对象类型可以使用 JSON.stringify进行转换,但是在接收时要注意使用try catch包裹,因为快应用默认发送的数据是对象类型且并没有stringify
      mounted () {
        const _this = this
        if (window.system && window.system.onmessage) {
          window.system.onmessage = function (data) {
            let d
            try {
              d = JSON.parse(data)
            } catch (err) {
            }
            if (d && d.page === 'quick_app') {
              _this.getInfo(d)
            }
         }
      }
      
  • [2] 注意发送数据的时机,发送数据一定要等待网页渲染完毕之后,否则在网页端将接收不到数据
    • 举例说明 —> 我想在页面渲染完成之后发送信息给web页面,因此我选择在快应用的onReady生命周期发送数据
      onReady(){
        // 此处可以拿到元素的
        this.$element('web').postMessage({
          message: '111111'
        })
      }
      
      但是我发现在网页在如下代码拿不到指定的信息
      mounted () {
        const _this = this
        if (window.system && window.system.onmessage) {
          window.system.onmessage = function (data) {
            console.log('data', data)
          }
        }
      } 
      
      原因是因为在发送数据的时候web网页还没有渲染完成!
      我们可以在web组件的pagefinish事件时传送数据,此事件在web页面渲染完成时触发
      @pagefinish="pagefinish"
      
      pagefinish(){
        this.$element('web').postMessage({
          message: '111111'
        })
      }
      
第三方组件库
  • https://vivoquickapp.github.io/apex-ui-docs/
  • https://jdsecretfe.github.io/quist-ui/
  • https://quickappcn.github.io/qaui/

css 样式问题

快应用中对于很多css样式都不兼容, 我们按照平常的习惯进行样式布局,在真机调试的时候发现样式是错乱的!


下面针对一些不兼容样式进行说明~

[1]选择器
  • 支持标签选择器、类选择器、id选择器,暂不支持其它选择器;
  • 继承:不支持样式继承;
[2]盒模型

快应用布局框架使用 border-box 模型,暂不支持 content-box 模型与手动指定 box-sizing 属性。

[3]样式布局-弹性布局

在快应用中很多组件默认采用的都是 弹性布局的方式进行布局,div组件是比较常用的弹性布局方式布局的元素。

  • 弹性布局不可以取消 ! ===> 在快应用中display只有flex与none取值情况,
      display: flex ; // 弹性布局
      display: none; //  消失
    
  • 若是不想子元素在一行排列 可以使用修改主轴方向
      flex-direction: column;
    
  • 注意:在弹性布局中 ===> 若是子元素的高度/宽度总和大于父元素的高度或宽度,不会出现滚动条,而是子元素的宽/高 收缩。
[4-1]样式切换 - 类名的动态切换

在很多情况下,我们需要通过动态切换类型来改变元素的的样式,在快应用中注意,切换类名时,类名必须在目标元素上,不然没效果!
比如设置在父元素上

.active{
  text{
    color: red; // 没效果
  }
}

我给text的父元素添加active类名然后修改text元素文本的颜色,但是发现没有效果;但是把类名动态添加在text标签上就发现样式可以正常切换了。

.active{
  color:red;
}
[4-2] 样式切换 - 行内样式动态切换

行内样式不支持动态编写 ----> 可以使用computed或methods

 <div style='{{background-image:url(imgurl)}}' class='www'>div>
  private:{
    imgurl: 'https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png'
  }

上述代码不能正常显示图片,个人猜测是因为识别不出变量imgurl,若是想样式中的数据动态切换,可以采用computed与methods

  <div style="{{returnStatusImage()}}"  class='www'>div>
private: {
   text: '快应用是什么?',
   status:0
},
returnStatusImage() {
   switch (this.status) {
     case 0:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png)'
       break;
     case 1:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/07167f84c6dbf2679a6b1744acdd6ae9.png)'
       break;
     case 2:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/743cbd9439d241cb6c8af9aeb85b312e.png)' 
       break;
     case 3:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/12/5459fe6f0978ca211dc7034b903547c2.png)'
       break;
     case -1:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/12/5459fe6f0978ca211dc7034b903547c2.png)'
       break;
     case 4:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2022/02/9ff11fe02d56737ed45dec1ff626a194.jpg)'
       break;
     default:
       return 'background-image:url(https://martin-upload.wcar.net.cn/web/2021/11/6bbf95698459f15b0050cb0d8e9e3484.png)'
   }
 },
[5]background
  • 在快应用中background属性的作用是用来设置渐变色的,不能作为背景的复合属性。
    • 起作用
      background: linear-gradient(53deg, #F0E6D5 0%, #F0DFC3 100%);
      
    • 无作用
      background: red;
      
    • 若是想设置颜色使用background-color
        background-color:red;
      
  • span组件添加背景色不起作用!若是想要设置背景色不要使用span组件
[6]overflow

在快应用中overflow可接受的属性值如下

overflow: visible; // 显示
overflow: hidden; // 隐藏

因此没有办法设置元素显示滚动条等

[7]border-radius

在快应用中border-radius只接受一个值作为属性值

  • 若是设置2/3/4个值,则会报出警告
    border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
    
    不支持px 20px 10px 0作为单位,在编译时会将第一个值后面的值看作为单位
  • 设置4个一样的值
    border-radius:30px 20px 10px 0; // 四个圆角都会设置为30px
    
  • 若是想四个圆角弧度不一致
    border-top-left-radius:30px; // 左上
    border-top-right-radius:30px; // 右上
    border-bottom-left-radius:30px; //  左下
    border-bottom-right-radius:30px; // 右下
    
[8]盒子阴影

快应用中不支持盒子阴影。

[9] 单位

快应用中支持 px % dp单位;但是%单位在真机中显示不对!

[10] 定位

定位没有层级 ----> 存在被覆盖导致点击事件不起作用的现象

系统接口

在项目中使用到的接口都需要在配置文件manifest.json中声明,不然会报如下警告

[WARN] 请在 manifest.json 文件里声明项目代码中用到的接口: system.storage, service.account, system.package, system.webview
[1] 检查某app是否在手机上安装
  • 官方文档:官方文档
  • 接口: system.package的hasInstalled方法
  • 作用:检查某app是否在已经在手机上安装
  • 使用
    • [1] 接口声明- 在配置文件manifest.json中声明
      "features": [
        {
          "name": "system.package" 
        },
      ]
      
    • [2] 在需要的地方导入并使用
        import pkg from '@system.package'
      
      pkg.hasInstalled({
        package: 'app包名',
        success: function(data) {
          console.log(`handling success: ${data.result}`)
          // result为true表示app已安装
          // result为false表示app未安装
        },
       fail: function(data, code) {
         console.log(`handling fail, code = ${code}`)
        }
      })
      
[2] 下载应用
  • 官方文档:官方文档
  • 接口: system.package的install方法
  • 作用:下载某app
  • 使用
    • [1] 接口声明- 在配置文件manifest.json中声明
      "features": [
        {
          "name": "system.package" 
        },
      ]
      
    • [2] 在需要的地方导入并使用
      import pkg from '@system.package'
      
      pkg.install({
        package: '应用包名',
       success: function(data) {
         console.log(`handling success: ${data.result}`)
         // result:true 下载成功
         // result: false 下载失败
       },
       fail: function(data, code) {
         console.log(`handling fail, code = ${code}`)
       }
      })
      
[3] 检查当前是否有桌面应用
  • 官方文档:官方文档
  • 接口: system.shortcut的hasInstalled方法
  • 作用:检查某app当前是否有桌面应用
  • 使用
    • [1] 接口声明- 在配置文件manifest.json中声明
      "features": [
        {
          "name": "system.shortcut" 
        },
      ]
      
    • [2] 在需要的地方导入并使用
      import shortcut from '@system.shortcut'
      
      shortcut.hasInstalled({
       success: function(res) {
         // res 为true表示已创建图标
         // res weifalse表示未创建图标
       }
      })
      
[4] 添加桌面应用
  • 官方文档:官方文档
  • 接口: system.shortcut的install方法
  • 作用:为某app添加桌面应用
  • 使用
    • [1] 接口声明- 在配置文件manifest.json中声明
      "features": [
        {
          "name": "system.shortcut" 
        },
      ]
      
    • [2] 在需要的地方导入并使用
      import shortcut from '@system.shortcut'
      
      shortcut.install({
        success: function() {
          console.log('handling success') // 创建成功
        },
        fail: function(data, code) {
         // 创建失败,请在设置中开启创建桌面应用权限
         console.log(`handling fail, code = ${code}, errorMsg=${data}`)
        }
      })
      
[5]数据存储
  • 官方文档:官方文档
[6]弹框
  • 官方文档:官方文档
  • 弹出框一共有三种
    • toast提示框
    • dialog对话框
    • 列表框
[7] 接口
  • 官方文档:官方文档
  • 请求封装
    import { fetch } from "@system.fetch";
    import { getStorage, setStorage } from './storage'
    const api = 'xxx' 
    
    const hasToken = async () => {
       const token = await getStorage('token')
       return !!token
    }
    
    // 将与后端约定的数据统一添加在请求头中
    const getHeaders = async () => {
       const token = await getStorage('token')
       return {
           token,
           ....
       }
    }
    
    export const httpGet = async (url, data = {}, header = {}) => {
     await hasToken()
     const headers = await getHeaders()
     return new Promise((resolve, reject) => {
       fetch({
         url: api + url,
         data,
         method: 'GET',
         responseType: 'json',
         header: {
           ...headers,
           ...header
         },
         success(data) {
           resolve(data.data)
         },
         fail(err) {
           reject(err)
         }
       })
     })
    }
    
    export const httpPost = async (url, data = {}, header = {}) => {
     await hasToken()
     const headers = await getHeaders()
     return new Promise((resolve, reject) => {
       fetch({
         url: api + url,
         data,
         method: 'POST',
         responseType: 'json',
         header: {
           ...header,
           ...headers
         },
         success(data) {
           if (data.data.status === 1004) {
             router.replace({
               uri: '/pages/Login'
             })
           } else {
             resolve(data.data)
           }
             
         },
         fail(err) {
           reject(err)
         }
       })
     })
    }
    
    export default {
     httpGet,
     httpPost
    }
    
    
[8]获取设备信息

获取设备信息 如屏幕高度

[9] 路由传参

在这里插入图片描述

数据

[1] 计算属性

计算属性

埋点

  • $umeng_stat

公共对象

global对象

在快应用中global对象可以直接使用,我们可以将封装的公共方法添加在global对象上(类似于将封装的公共方法添加在vue实例化对象上)

$app
退出快应用
this.$app.exit() // 退出开应用,结束应用生命周期
$element
获取指定element元素
  • 获取指定 id 的组件 dom 对象,如果没有指定 id,则返回根组件 dom 对象用法
    this. $element('id名')
    
  • 获取元素的宽高
     element.getBoundingClientRect({
       success: data =>{
         // data中包含元素的宽高 ,left\right\bottom\top
       }
     })
    

manifest配置文件

manifest配置文件

config - 系统配置信息
designWidth - 项目配置基准宽度

与传统 web 页面不同,px是相对于项目配置基准宽度的单位,已经适配了移动端屏幕,其原理类似于rem。

设计稿1px / 设计稿基准宽度 = 框架样式1px / 项目配置基准宽度

  • 语法
    "config":{
      "designWidth": 750
    }
    
    若是不设置,默认值为750
  • 举例说明
    前端开发_快应用开发_第3张图片
data - 全局数据对象

属性名不能以$_开头,在页面中可通过 this 进行访问;如果全局数据属性与页面的数据属性重名,则页面初始化时,全局数据会覆盖页面中对应的属性值

router - 配置路由

文件的目录结构如下:

src
  — pages
         — Demo
                 — index.ux
         — DemoDetail
                 — index.ux
          — Test
                 — test.ux
                 — test2.ux

在这里插入图片描述

entry

entry的属性值必须为pages中的一个。

pages
pages:{
  "页面名称":{
    "conponent": ' 文件夹名',
    "path": "路径名"
  }
}
  • 注意事项1: 页面配置列表(key值为指定页面名称(页面对应的文件夹目录),value为页面详细配置; key值唯一)

    • 若是同一文件夹下存在多个文件,此时不能为该文件下的多个文件进行路由匹配

       "pages/Test": {
          "component": "test",
          "path": "/test1"
        },
        "pages/Test": {
          "component": "test2",
          "path": "/test2"
        }
      

      我想为同一文件夹下的文件匹配多个路由,此时会报错 Duplicate object key(重复配置)

      因此不要为同一文件夹的文件配置路由

    • 通过路由的路径可以看出,(在没有添加path属性的情况下)路径只到指定的文件夹而不包含文件名,因此即使是component属性值不同路由的路径也是相同的!

       "pages/Test": {
          "component": "test"
        }
      

      这个配置之后的路径是’pages/Test’

       "pages/Test": {
          "component": "test2"
        }
      

      这个配置之后的路径也是’pages/Test’

  • 注意事项2: 若是在定义单个路由信息时,存在path属性,属性值前面一定要加/表示当前在src文件夹下。

    • 在定义单个路由信息时,若是没有添加对应的path属性时,页面名称就是对应的路径名

      "pages": {
        "pages/DemoDetail": {
          "component": "index"
      }
      

      当url为’/pages/DemoDetail’就会跳转到该页面了,此时location.href的值为

      http://localhost:8083/preview/pages/DemoDetail/

    • 若是添加了path属性,页面的路径将会以path的属性值为准

      "pages/DemoDetail": {
         "component": "index",
         "path": "/detail"
       }
      

      此时当url为’detail’或’/detail’时都会跳转到该页面,此时location.href的值为

      http://localhost:8083/preview/detail/

      此时注意path属性值前面一定要加/, 不然就会匹配不到对应的页面

      "pages/DemoDetail": {
         "component": "index",
         "path": "detail"
       }
      

      此时当当url为’detail’或’/detail’时会报错 404

      http://localhost:8083/preview/detail is not found

你可能感兴趣的:(javascript,css,css3,前端)