HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

建议UniApp的模板模式也可以支持Vue新语法,自定义组件模式兼容性问题太多了

uniapp

一切都是bug呀。已经快做完的项目,没办法完全重构它这个自定义组件模式

一切都是bug呀。已经快做完的项目,没办法完全重构它这个自定义组件模式

uni-app 1.9发布,App平台升级为新版编译器(自定义组件模式),支持更多Vue语法

性能

uni-app 1.8版重写框架,实现了微信端的性能翻倍,并增加了若干Vue语法支持,详见

之后,众多开发者呼吁将新框架尽快迁移到App平台,经过2周8个Alpha版的迭代,uni-app团队完成新框架在App平台的迁移适配工作,至此1.9版正式发布。

新版特性

uni-app 1.9版主要改进包括:

  • 插件市场支持付费原生插件,欢迎插件作者们踊跃提交原生插件,示例https://ext.dcloud.net.cn/plugin?id=135
  • 引擎架构升级,提升App启动速度、减少js阻塞
  • 支持自定义组件模式的新编译器,大幅提升App端的组件性能、支持过滤器等更多vue语法
  • 很多开发者报包括uni ui的折叠面板、swipeaction等组件中无法使用v-for也需要使用新版并配置新编译模式解决。

新版支持了更多 Vue 语法,详细如下:

  • 支持过滤器 filter
  • 支持比较复杂的 JavaScript 渲染表达式
  • 支持在 template 内使用 methods 中的函数
  • 支持 v-html (同 rich-text 的解析)
  • 支持 v-slot 新语法
  • 支持解构插槽 Prop 设置默认值
  • 支持 slot 后备内容
  • 组件支持原生事件绑定,如:@tap.native

新版不支持的 vue 语法

  • class不支持绑定Obejct变量(使用字符串的形式绑定)
  • 不支持事件修饰符:prevent、passive(在App与小程序平台,使用stop修饰符,既可以阻止冒泡也能阻止默认行为)
  • 不支持render、inline-template、X-Templates、keep-alive、transition
  • 不支持使用 Vue.use 的方式注册全局组件(在main.js使用Vue.component的方式引入)

新旧版本兼容策略

为兼容历史项目,uni-app 现阶段同时支持老的template模板模式、和新的自定义组件模式两种模式,默认策略如下:

  • HBuilderX 1.9.0+ 新创建的项目,在微信端、App端默认会启用新的框架;
  • 历史项目默认使用老框架。如需启动新框架请按下面配置开启。
  • 注意HBuilderX Alpha版默认使用新框架,若改用1.9正式版后,也需要手动配置开启新框架。

开发者可在manifest.json的源码视图里配置, manifest.json -> app-plus -> usingComponents切换编译模式,如下:

// manifest.json  
{  
    // ...  
    /* App平台特有配置 */  
    "app-plus": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
    /* 微信小程序特有配置 */  
    "mp-weixin": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
}  

Tips:

  • 为保证自定义组件兼容性,运行到微信开发者工具时,建议将微信基础库设置为最新版本(微信工具项目设置中)。
  • 如果你使用了新增的vue语法,请注意只有App、H5、微信三个平台支持这些新语法,编译到其他平台时,要用条件编译处理。
  • 如发现新框架有bug,开发者可通过manifest.json切回老框架编译模式,同时欢迎在 ask 社区反馈bug

新版开发注意事项

开发者启用自定义组件模式后,需注意部分开发事项,参考https://ask.dcloud.net.cn/article/35851

Tips:新编译模式在App端,控制台打印的日志无法体现源码的准确行数的问题,需升级到1.9.2版本。

性能优化建议

  1. 模板中不建议直接使用 object
<!-- 低性能写法 -->  
<uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="{color: '#4cd964',size: '22',type: 'spinner'}"></uni-title>  
<!-- 高性能写法 -->  
<template>  
    <view>  
        <uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="extraIcon"></uni-title>  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            extraIcon:{color: '#4cd964',size: '22',type: 'spinner'}  
        }  
    }  
}  
</script>  
  1. 在模板中未使用的数据不建议定义在data 中,未使用的数据一律移除到 vm 外边定义
<!-- 低性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            name:'',  
            types:true  
        }  
    },  
    onLoad(){  
        if(this.types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
<!-- 高性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
let types = true ;  
export default {  
    data() {  
        return {  
            name:''  
        }  
    },  
    onLoad(){  
        if(types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
  1. 为提升开发体验,新版本增加了部分 Vue 语法,其实这些语法在微信小程序中本身是不支持的;为支持这些语法,uni-app 会在编译、运行时分别做一些额外的工作,若开发者希望追求性能极致,则建议尽量少用或者不用新增语法。

老项目改造注意

老版编译模式升级新版编译模式,可先在manifest的源码视图中,在微信下打开新编译模式,运行到小程序调试。然后再迁到app端。

请一定注意新版编译模式,必须与新版手机sdk、基座、打包机、cli绑定。即使HBuilderX升级,如果你的项目是cli方式、或使用了老的自定义基座、或本地sdk离线打包,则需手动升级这些,否则会造成白屏等多种异常。详见https://ask.dcloud.net.cn/article/35845

后续

新框架会陆续把新编译器迁移到其他端的小程序上,并同步进行App端的nvue的强化工作。

升级注意

如果你的项目是cli创建的,记得编译器在你的项目下,不会随着HBuilderX升级而升级,你需要npm update手动升级编译器。

继续阅读 »

uni-app 1.8版重写框架,实现了微信端的性能翻倍,并增加了若干Vue语法支持,详见

之后,众多开发者呼吁将新框架尽快迁移到App平台,经过2周8个Alpha版的迭代,uni-app团队完成新框架在App平台的迁移适配工作,至此1.9版正式发布。

新版特性

uni-app 1.9版主要改进包括:

  • 插件市场支持付费原生插件,欢迎插件作者们踊跃提交原生插件,示例https://ext.dcloud.net.cn/plugin?id=135
  • 引擎架构升级,提升App启动速度、减少js阻塞
  • 支持自定义组件模式的新编译器,大幅提升App端的组件性能、支持过滤器等更多vue语法
  • 很多开发者报包括uni ui的折叠面板、swipeaction等组件中无法使用v-for也需要使用新版并配置新编译模式解决。

新版支持了更多 Vue 语法,详细如下:

  • 支持过滤器 filter
  • 支持比较复杂的 JavaScript 渲染表达式
  • 支持在 template 内使用 methods 中的函数
  • 支持 v-html (同 rich-text 的解析)
  • 支持 v-slot 新语法
  • 支持解构插槽 Prop 设置默认值
  • 支持 slot 后备内容
  • 组件支持原生事件绑定,如:@tap.native

新版不支持的 vue 语法

  • class不支持绑定Obejct变量(使用字符串的形式绑定)
  • 不支持事件修饰符:prevent、passive(在App与小程序平台,使用stop修饰符,既可以阻止冒泡也能阻止默认行为)
  • 不支持render、inline-template、X-Templates、keep-alive、transition
  • 不支持使用 Vue.use 的方式注册全局组件(在main.js使用Vue.component的方式引入)

新旧版本兼容策略

为兼容历史项目,uni-app 现阶段同时支持老的template模板模式、和新的自定义组件模式两种模式,默认策略如下:

  • HBuilderX 1.9.0+ 新创建的项目,在微信端、App端默认会启用新的框架;
  • 历史项目默认使用老框架。如需启动新框架请按下面配置开启。
  • 注意HBuilderX Alpha版默认使用新框架,若改用1.9正式版后,也需要手动配置开启新框架。

开发者可在manifest.json的源码视图里配置, manifest.json -> app-plus -> usingComponents切换编译模式,如下:

// manifest.json  
{  
    // ...  
    /* App平台特有配置 */  
    "app-plus": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
    /* 微信小程序特有配置 */  
    "mp-weixin": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
}  

Tips:

  • 为保证自定义组件兼容性,运行到微信开发者工具时,建议将微信基础库设置为最新版本(微信工具项目设置中)。
  • 如果你使用了新增的vue语法,请注意只有App、H5、微信三个平台支持这些新语法,编译到其他平台时,要用条件编译处理。
  • 如发现新框架有bug,开发者可通过manifest.json切回老框架编译模式,同时欢迎在 ask 社区反馈bug

新版开发注意事项

开发者启用自定义组件模式后,需注意部分开发事项,参考https://ask.dcloud.net.cn/article/35851

Tips:新编译模式在App端,控制台打印的日志无法体现源码的准确行数的问题,需升级到1.9.2版本。

性能优化建议

  1. 模板中不建议直接使用 object
<!-- 低性能写法 -->  
<uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="{color: '#4cd964',size: '22',type: 'spinner'}"></uni-title>  
<!-- 高性能写法 -->  
<template>  
    <view>  
        <uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="extraIcon"></uni-title>  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            extraIcon:{color: '#4cd964',size: '22',type: 'spinner'}  
        }  
    }  
}  
</script>  
  1. 在模板中未使用的数据不建议定义在data 中,未使用的数据一律移除到 vm 外边定义
<!-- 低性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            name:'',  
            types:true  
        }  
    },  
    onLoad(){  
        if(this.types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
<!-- 高性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
let types = true ;  
export default {  
    data() {  
        return {  
            name:''  
        }  
    },  
    onLoad(){  
        if(types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
  1. 为提升开发体验,新版本增加了部分 Vue 语法,其实这些语法在微信小程序中本身是不支持的;为支持这些语法,uni-app 会在编译、运行时分别做一些额外的工作,若开发者希望追求性能极致,则建议尽量少用或者不用新增语法。

老项目改造注意

老版编译模式升级新版编译模式,可先在manifest的源码视图中,在微信下打开新编译模式,运行到小程序调试。然后再迁到app端。

请一定注意新版编译模式,必须与新版手机sdk、基座、打包机、cli绑定。即使HBuilderX升级,如果你的项目是cli方式、或使用了老的自定义基座、或本地sdk离线打包,则需手动升级这些,否则会造成白屏等多种异常。详见https://ask.dcloud.net.cn/article/35845

后续

新框架会陆续把新编译器迁移到其他端的小程序上,并同步进行App端的nvue的强化工作。

升级注意

如果你的项目是cli创建的,记得编译器在你的项目下,不会随着HBuilderX升级而升级,你需要npm update手动升级编译器。

收起阅读 »

HBuilderX: vue doc使用教程

vuedoc HBuilderX

重要:文档已迁移至 https://hx.dcloud.net.cn/Tutorial/Language/vuedoc

HBuilderX 1.9.0 新增了vue doc功能

什么是 vue doc ?

可以理解为,vue组件使用说明。

在其它文件,使用组件的时候,弹出代码提示。

什么是组件?组件是可复用的 Vue 实例,且带有一个名字。

语法

主要用在script部分,需要写在export default上面

/**  
* 这里是一个组件描述,会在提示标签的时候显示  
* @description 这里也是一个组件描述  
* @tutorial https://uniapp.dcloud.io/api/media/image?id=chooseimage  
* @property {String} type = [button|input|...值域] 这里是属性描述  
* @event {Function} tap 这是是事件描述   
* @example 这里是示例代码  
*/

其中@property和@event内{ }中间的是类型,event的类型必须是Function

示例

<script>  
  /**  
   * 翻页组件  
   * @description 翻页组件  
   * @tutorial http://www.baidu.com  
   * @property {Number} total 翻页数据总数  
   * @property {String} size = [big|small] 组件大小  
   * @event {Function} close 关闭事件  
   * @example <Pagination @total="50" @close=""></Pagination>  
   */  
  export default {  
    props: {  
      "total": Number,  
      "size": String  
    },  
    data () {  
      return {  
        pageSize: 10,  
        pageNumber: 0  
      }  
    },  
    methods: {  
      handleChange(data, event) {  
        this.$emit('PsPn', this.pageSize, this.pageNumber)  
      }  
    }  
  }  
</script>

组件提示,效果如下:

属性提示:

事件提示:

继续阅读 »

重要:文档已迁移至 https://hx.dcloud.net.cn/Tutorial/Language/vuedoc

HBuilderX 1.9.0 新增了vue doc功能

什么是 vue doc ?

可以理解为,vue组件使用说明。

在其它文件,使用组件的时候,弹出代码提示。

什么是组件?组件是可复用的 Vue 实例,且带有一个名字。

语法

主要用在script部分,需要写在export default上面

/**  
* 这里是一个组件描述,会在提示标签的时候显示  
* @description 这里也是一个组件描述  
* @tutorial https://uniapp.dcloud.io/api/media/image?id=chooseimage  
* @property {String} type = [button|input|...值域] 这里是属性描述  
* @event {Function} tap 这是是事件描述   
* @example 这里是示例代码  
*/

其中@property和@event内{ }中间的是类型,event的类型必须是Function

示例

<script>  
  /**  
   * 翻页组件  
   * @description 翻页组件  
   * @tutorial http://www.baidu.com  
   * @property {Number} total 翻页数据总数  
   * @property {String} size = [big|small] 组件大小  
   * @event {Function} close 关闭事件  
   * @example <Pagination @total="50" @close=""></Pagination>  
   */  
  export default {  
    props: {  
      "total": Number,  
      "size": String  
    },  
    data () {  
      return {  
        pageSize: 10,  
        pageNumber: 0  
      }  
    },  
    methods: {  
      handleChange(data, event) {  
        this.$emit('PsPn', this.pageSize, this.pageNumber)  
      }  
    }  
  }  
</script>

组件提示,效果如下:

属性提示:

事件提示:

收起阅读 »

拍照,相册,读取图片转成File

相册 拍照
/* global plus:true */  
/* eslint prefer-promise-reject-errors: "error" */  

/*  
拍照 = capture = readFile + saveInGallery  
*  
相册 = readFile  
*  
readFile = compress + checkSize + turnToFile  
         = 压缩》检查大小(this.maxSize)》转成File文件  
*/  

class UploadImg {  
  constructor () {  
    this.maxSize = 5 // 最大5M  
    this.quality = 20 // 1-100,越高图越大  
  }  
  capture () {  
    plus.nativeUI.showWaiting();  
    const _this = this  
    var cmr = plus.camera.getCamera();  
    // res分辨率  
    var res = cmr.supportedImageResolutions[0];  
    // fmt文件格式  
    var fmt = cmr.supportedImageFormats[0];  
    return new Promise((resolve, reject) => {  
      cmr.captureImage(function (p) {  
        Promise.all([_this.saveInGallery(p), resolve(_this.readFile(p))])  
          .then(() => plus.nativeUI.closeWaiting())  
          .catch(() => plus.nativeUI.closeWaiting())  
      },  
      function (error) {  
        reject(error)  
        plus.nativeUI.closeWaiting()  
      }, {  
        resolution: res,  
        format: fmt  
      })  
    })  
  }  
  gallery () {  
    plus.nativeUI.showWaiting();  
    const _this = this  
    return new Promise((resolve, reject) => {  
      plus.gallery.pick(  
        function (p) {  
          Promise.all([resolve(_this.readFile(p))])  
            .then(() => plus.nativeUI.closeWaiting())  
            .catch(() => plus.nativeUI.closeWaiting())  
        },  
        function (cancel) {  
          reject(cancel)  
          plus.nativeUI.closeWaiting()  
        }, {  
          filter: 'image'  
        }  
      )  
    })  
  }  
  saveInGallery (p) {  
    plus.gallery.save(p, function () {  
      console.log('保存进相册-成功')  
    },  
    function () {  
      console.log('保存进相册-失败')  
    })  
  }  
  compress (p) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      plus.zip.compressImage({  
        src: p,  
        dst: '_doc/compress.jpg',  
        overwrite: true,  
        quality: _this.quality  
      },  
      function (file) {  
        resolve(file.target)  
      },  
      function (error) {  
        console.log('压缩失败');  
        reject(error)  
      });  
    })  
  }  
  checkSize (size) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      const num = 1024;  
      const fileSize = (size / Math.pow(num, 2)).toFixed(2);  
      if (fileSize > _this.maxSize) {  
        plus.nativeUI.alert(`图片不得超过${_this.maxSize}M`);  
        reject(new Error('overSize'));  
      } else {  
        resolve()  
      }  
    })  
  }  
  readFile (p) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      this.compress(p).then((p) => {  
        plus.io.resolveLocalFileSystemURL(p, function (fs) {  
          fs.file(function (file) {  
            _this.checkSize(file.size)  
              .then(() => {  
                resolve(_this.turnToFile(fs, file))  
              })  
              .catch(error => {  
                console.log(error)  
              })  
          });  
        });  
      })  
    });  
  }  
  turnToFile (fs, oldFile) {  
    return new Promise((resolve, reject) => {  
      var reader = new plus.io.FileReader();  
      reader.readAsDataURL(oldFile)  
      reader.onloadend = function (e) {  
        // e.target.result  
        let data = e.target.result  
        // object专成file  
        let file = (function (path, name) {  
          let arr = path.split(',')  
          let mime = arr[0].match(/:(.*?);/)[1]  
          let bstr = atob(arr[1])  
          let n = bstr.length  
          let u8arr = new Uint8Array(n)  
          while (n--) {  
            u8arr[n] = bstr.charCodeAt(n);  
          }  
          return new File([u8arr], name, {  
            type: mime  
          });  
        })(e.target.result, fs.name);  
        resolve({  
          data: data,  
          file: file  
        })  
      };  
    })  
  }  
}  
export const uploadImg = new UploadImg()
继续阅读 »
/* global plus:true */  
/* eslint prefer-promise-reject-errors: "error" */  

/*  
拍照 = capture = readFile + saveInGallery  
*  
相册 = readFile  
*  
readFile = compress + checkSize + turnToFile  
         = 压缩》检查大小(this.maxSize)》转成File文件  
*/  

class UploadImg {  
  constructor () {  
    this.maxSize = 5 // 最大5M  
    this.quality = 20 // 1-100,越高图越大  
  }  
  capture () {  
    plus.nativeUI.showWaiting();  
    const _this = this  
    var cmr = plus.camera.getCamera();  
    // res分辨率  
    var res = cmr.supportedImageResolutions[0];  
    // fmt文件格式  
    var fmt = cmr.supportedImageFormats[0];  
    return new Promise((resolve, reject) => {  
      cmr.captureImage(function (p) {  
        Promise.all([_this.saveInGallery(p), resolve(_this.readFile(p))])  
          .then(() => plus.nativeUI.closeWaiting())  
          .catch(() => plus.nativeUI.closeWaiting())  
      },  
      function (error) {  
        reject(error)  
        plus.nativeUI.closeWaiting()  
      }, {  
        resolution: res,  
        format: fmt  
      })  
    })  
  }  
  gallery () {  
    plus.nativeUI.showWaiting();  
    const _this = this  
    return new Promise((resolve, reject) => {  
      plus.gallery.pick(  
        function (p) {  
          Promise.all([resolve(_this.readFile(p))])  
            .then(() => plus.nativeUI.closeWaiting())  
            .catch(() => plus.nativeUI.closeWaiting())  
        },  
        function (cancel) {  
          reject(cancel)  
          plus.nativeUI.closeWaiting()  
        }, {  
          filter: 'image'  
        }  
      )  
    })  
  }  
  saveInGallery (p) {  
    plus.gallery.save(p, function () {  
      console.log('保存进相册-成功')  
    },  
    function () {  
      console.log('保存进相册-失败')  
    })  
  }  
  compress (p) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      plus.zip.compressImage({  
        src: p,  
        dst: '_doc/compress.jpg',  
        overwrite: true,  
        quality: _this.quality  
      },  
      function (file) {  
        resolve(file.target)  
      },  
      function (error) {  
        console.log('压缩失败');  
        reject(error)  
      });  
    })  
  }  
  checkSize (size) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      const num = 1024;  
      const fileSize = (size / Math.pow(num, 2)).toFixed(2);  
      if (fileSize > _this.maxSize) {  
        plus.nativeUI.alert(`图片不得超过${_this.maxSize}M`);  
        reject(new Error('overSize'));  
      } else {  
        resolve()  
      }  
    })  
  }  
  readFile (p) {  
    const _this = this  
    return new Promise((resolve, reject) => {  
      this.compress(p).then((p) => {  
        plus.io.resolveLocalFileSystemURL(p, function (fs) {  
          fs.file(function (file) {  
            _this.checkSize(file.size)  
              .then(() => {  
                resolve(_this.turnToFile(fs, file))  
              })  
              .catch(error => {  
                console.log(error)  
              })  
          });  
        });  
      })  
    });  
  }  
  turnToFile (fs, oldFile) {  
    return new Promise((resolve, reject) => {  
      var reader = new plus.io.FileReader();  
      reader.readAsDataURL(oldFile)  
      reader.onloadend = function (e) {  
        // e.target.result  
        let data = e.target.result  
        // object专成file  
        let file = (function (path, name) {  
          let arr = path.split(',')  
          let mime = arr[0].match(/:(.*?);/)[1]  
          let bstr = atob(arr[1])  
          let n = bstr.length  
          let u8arr = new Uint8Array(n)  
          while (n--) {  
            u8arr[n] = bstr.charCodeAt(n);  
          }  
          return new File([u8arr], name, {  
            type: mime  
          });  
        })(e.target.result, fs.name);  
        resolve({  
          data: data,  
          file: file  
        })  
      };  
    })  
  }  
}  
export const uploadImg = new UploadImg()
收起阅读 »

mac系统下面的HX工具下载插件都提示失败

mac系统下面的HX工具下载插件都提示失败,这个要怎么办

mac系统下面的HX工具下载插件都提示失败,这个要怎么办

getApp() 挂载实例方法

在编译后的dist中,我们可以看到如下

只有hooks中的function才会被挂载在getApp()上,若需要在getApp()上添加全局funciton或对象,需修改hooks。

或直接修改dccloudio源码,可以省去每次构建后的修改

继续阅读 »

在编译后的dist中,我们可以看到如下

只有hooks中的function才会被挂载在getApp()上,若需要在getApp()上添加全局funciton或对象,需修改hooks。

或直接修改dccloudio源码,可以省去每次构建后的修改

收起阅读 »

汽车钥匙怎么解码器原理(详细介绍)

汽车钥匙怎么解码器原理【136(电)310(微)87961】​【诚.信.为.本】【质.量.保.证】【效.率.第.一】包您满意中新网6月20日电 据外媒报道,当地时间19日,美国宣布退出联合国人权理事会(UNHRC),指责人权理事会“长久以来对以色列存有偏见”。联合国对美国做
出该决定表示失望。
据报道,美国驻联合国大使妮基?黑莉(Nikki Haley)宣布美国退出人权理事会时,美国国务卿蓬佩奥就站在她旁边。对美国退出联合国人权理事会的行为,黑
莉抨击称,美国呼吁改革该机构,但呼声一直没有得到重视。
特朗普政府长久以来一直扬言,如果不彻底改革人权理事会,美国将退出。在小布什当政时期,美国曾以人权理事会充满以色列的敌人为由, 对其抵制长达
三年,直到2009年奥巴马当政才重回该组织。
联合国对美国的退出表示失望。联合国秘书长古特雷斯的发言人表示,“联合国秘书长更希望美国能继续留在联合国人权理事会”,“该机构在促进和保护全
世界的人权方面,发挥着非常重要的作用”。
此外,报道称,该举动立即遭到了十几个慈善团体的谴责,他们写信给国务卿蓬佩奥,称他们“对政府决定从联合国人权理事会中退出的决定深感失望”,称
该机构是全球级别的政府间人权机构。
据报道,联合国人权理事会总部设在日内瓦,是一个负责维护人权的、拥有47个成员的联合国机构。目前,美国因在美墨边界强制儿童和其移民父母分离而遭
受猛烈抨击。联合国人权事务高级专员胡笙昨天呼吁华盛顿停止这项“不合理”的政策​

继续阅读 »

汽车钥匙怎么解码器原理【136(电)310(微)87961】​【诚.信.为.本】【质.量.保.证】【效.率.第.一】包您满意中新网6月20日电 据外媒报道,当地时间19日,美国宣布退出联合国人权理事会(UNHRC),指责人权理事会“长久以来对以色列存有偏见”。联合国对美国做
出该决定表示失望。
据报道,美国驻联合国大使妮基?黑莉(Nikki Haley)宣布美国退出人权理事会时,美国国务卿蓬佩奥就站在她旁边。对美国退出联合国人权理事会的行为,黑
莉抨击称,美国呼吁改革该机构,但呼声一直没有得到重视。
特朗普政府长久以来一直扬言,如果不彻底改革人权理事会,美国将退出。在小布什当政时期,美国曾以人权理事会充满以色列的敌人为由, 对其抵制长达
三年,直到2009年奥巴马当政才重回该组织。
联合国对美国的退出表示失望。联合国秘书长古特雷斯的发言人表示,“联合国秘书长更希望美国能继续留在联合国人权理事会”,“该机构在促进和保护全
世界的人权方面,发挥着非常重要的作用”。
此外,报道称,该举动立即遭到了十几个慈善团体的谴责,他们写信给国务卿蓬佩奥,称他们“对政府决定从联合国人权理事会中退出的决定深感失望”,称
该机构是全球级别的政府间人权机构。
据报道,联合国人权理事会总部设在日内瓦,是一个负责维护人权的、拥有47个成员的联合国机构。目前,美国因在美墨边界强制儿童和其移民父母分离而遭
受猛烈抨击。联合国人权事务高级专员胡笙昨天呼吁华盛顿停止这项“不合理”的政策​

收起阅读 »

wap2app关于禁用原生标题解决方法【详细篇】

原生标题

这个问题每个刚接触HBuilderX打包wap2app的新手大部分都会面临这个问题,于是不断的有人发帖求助,坟贴被挖掘。当自己问题解决后就消声灭迹不在来关系这个初级问题。
官方团队已经给出解决方案,此等级别的问题不会太在意,不会重复的回复,给的解决方法也比较笼统,很多新手不知所云,根本不知道具体要怎么做。
你在度娘搜索出来的所谓解决方法无非就是

"titleNView": false, //禁用原生标题栏

这个方法正确吗?答案当然是正确。你的问题解决了吗?答案是当然没有解决。那么为题出在哪里呢??

问题就出在新手需要一份简单到 贴出代码直接复制粘贴就能解决问题的程度,

详细如下:
在sitemap.json的pages数组的最后,也就是

 "pages": [  
        {  
            "webviewId": "__W2A__www.d44ll.xyz",//首页  
            "matchUrls": [  
                {  
                    "href": "http://60.205.000.126:3388"   
                }, {  
                    "href": "http://60.205.000.126:3388/"  
                }  
            ],  
            "webviewParameter": {  
                "titleNView": false,  
                "statusbar": {  
                    //状态条背景色,  
                    //首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致  
                    //若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;  
                    "style": "dark"  
                    //"background": "#009688",  
                    //"color": "#fff"  
                }  
            }  
        },  
     ///////////////////////////////////////////////////////这里//////////////////////////////////////////////////////////////////////  

    {//未适配的公共页面,可拦截原生下载和头部导航栏, 注:通配符的规则 放在最后一个节点才能达到适配所有未适配的公共页面效果,适配规则优先级为自上而下查找匹配规则  
            "webviewId": "common",  
            "matchUrls": [  
                {  
                    "hostname": "R:.*",  
                    "pathname": "R:.*"  
                }  
            ],  
            "webviewParameter": {  
                "titleNView": false  
            }  
        }  
 ///////////////////////////////////////////////////////到这里//////////////////////////////////////////////////////////////////////  
    ]

官方团队的答案:

首先说明,我们建议隐藏HTML的头,而不是隐藏wap2app的原生头。
因为wap2app的原生头渲染更快,页面加载时不会出现整屏白屏的情况。
如果原来的HTML头有业务逻辑,可以迁移到wap2app的原生头上。

补充说明:titleNView:false 是有效的。前提是需要适配到相应的webviewid。

如果是未适配的页面,也会打开新窗口。但是webviewid是随机给的,这时候框架默认会配置一个原生导航栏,如果要在这种情况下禁掉原生导航栏,建议仿照hello wap2app 示例操作,在sitemap.json的pages数组的最后,注意是最后(适配url规则为从上而下),配置一个webviewid为common的webview,来容纳所有会随机打开的窗口,进行你的操作。

hello wap2app 示例获取方法:
HBuilder 更新至最新alpha版本,新建wap2app --> 选择模板 hello wap2app

http://ask.dcloud.net.cn/question/57947

其实就算这么做,感觉也还是不够完美,会出现第二个问题:http://ask.dcloud.net.cn/question/68271

继续阅读 »

这个问题每个刚接触HBuilderX打包wap2app的新手大部分都会面临这个问题,于是不断的有人发帖求助,坟贴被挖掘。当自己问题解决后就消声灭迹不在来关系这个初级问题。
官方团队已经给出解决方案,此等级别的问题不会太在意,不会重复的回复,给的解决方法也比较笼统,很多新手不知所云,根本不知道具体要怎么做。
你在度娘搜索出来的所谓解决方法无非就是

"titleNView": false, //禁用原生标题栏

这个方法正确吗?答案当然是正确。你的问题解决了吗?答案是当然没有解决。那么为题出在哪里呢??

问题就出在新手需要一份简单到 贴出代码直接复制粘贴就能解决问题的程度,

详细如下:
在sitemap.json的pages数组的最后,也就是

 "pages": [  
        {  
            "webviewId": "__W2A__www.d44ll.xyz",//首页  
            "matchUrls": [  
                {  
                    "href": "http://60.205.000.126:3388"   
                }, {  
                    "href": "http://60.205.000.126:3388/"  
                }  
            ],  
            "webviewParameter": {  
                "titleNView": false,  
                "statusbar": {  
                    //状态条背景色,  
                    //首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致  
                    //若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;  
                    "style": "dark"  
                    //"background": "#009688",  
                    //"color": "#fff"  
                }  
            }  
        },  
     ///////////////////////////////////////////////////////这里//////////////////////////////////////////////////////////////////////  

    {//未适配的公共页面,可拦截原生下载和头部导航栏, 注:通配符的规则 放在最后一个节点才能达到适配所有未适配的公共页面效果,适配规则优先级为自上而下查找匹配规则  
            "webviewId": "common",  
            "matchUrls": [  
                {  
                    "hostname": "R:.*",  
                    "pathname": "R:.*"  
                }  
            ],  
            "webviewParameter": {  
                "titleNView": false  
            }  
        }  
 ///////////////////////////////////////////////////////到这里//////////////////////////////////////////////////////////////////////  
    ]

官方团队的答案:

首先说明,我们建议隐藏HTML的头,而不是隐藏wap2app的原生头。
因为wap2app的原生头渲染更快,页面加载时不会出现整屏白屏的情况。
如果原来的HTML头有业务逻辑,可以迁移到wap2app的原生头上。

补充说明:titleNView:false 是有效的。前提是需要适配到相应的webviewid。

如果是未适配的页面,也会打开新窗口。但是webviewid是随机给的,这时候框架默认会配置一个原生导航栏,如果要在这种情况下禁掉原生导航栏,建议仿照hello wap2app 示例操作,在sitemap.json的pages数组的最后,注意是最后(适配url规则为从上而下),配置一个webviewid为common的webview,来容纳所有会随机打开的窗口,进行你的操作。

hello wap2app 示例获取方法:
HBuilder 更新至最新alpha版本,新建wap2app --> 选择模板 hello wap2app

http://ask.dcloud.net.cn/question/57947

其实就算这么做,感觉也还是不够完美,会出现第二个问题:http://ask.dcloud.net.cn/question/68271

收起阅读 »

mui实现每个跳转页面刷新数据的的方法

第一步给自己的跳转页面方法加个自定义方法


第二步修改mui.js里面源代码


第三步页面监听方法做自己处理

这样可以处理数据刷新的问题,免得一个一个页面mui.fire写自己都忘了怎么调用,毕竟一个项目页面多了,直接改源码,每个页面监听一下自己的方法处理业务,还要顺便吐槽一下官方文档太少了,建议大家直接看5+api和mui.js里面源码,大部分问题就能解决了,官方文档是看不出来什么的

继续阅读 »

第一步给自己的跳转页面方法加个自定义方法


第二步修改mui.js里面源代码


第三步页面监听方法做自己处理

这样可以处理数据刷新的问题,免得一个一个页面mui.fire写自己都忘了怎么调用,毕竟一个项目页面多了,直接改源码,每个页面监听一下自己的方法处理业务,还要顺便吐槽一下官方文档太少了,建议大家直接看5+api和mui.js里面源码,大部分问题就能解决了,官方文档是看不出来什么的

收起阅读 »

第一章(序):MUI集成个推、信鸽推送,华为推送、小米推送、魅族推送

个推SDK

此教程针对使用MUI开发的APP,(若使用uni-app,则按照官方文档即可,其实他们也是做了我说的这些工作)

MUI官方已经停止维护,因此想要APP离线推送必看此教程

APP离线推送是业界一大难题,特别是Android机,国内手机厂商都阉割掉谷歌的推送服务,同时对后台进程严格限制,某些厂商甚至严格限制APP相互包活机制,所以难以保证用户能收到离线消息;
但APP离不开离线推送,像微信、QQ等大厂被国内各手机厂商加入系统级白名单,能保证实时到达率,对于小厂来说只能使用我说的办法。
教程要点:
1、APP需要离线打包;
2、集成个推(后公司要求改为集成了信鸽推送);
3、集成华为推送;
4、集成小米推送;
5、集成魅族推送;
此教程,需要有MUI开发经验,需要一点APP原生开发能力,不过按照我说的一步一来即可;

未完待续....

,若你急需此功能,加QQ:944515900,帮你解决,给个红包犒劳一下就行;

继续阅读 »

此教程针对使用MUI开发的APP,(若使用uni-app,则按照官方文档即可,其实他们也是做了我说的这些工作)

MUI官方已经停止维护,因此想要APP离线推送必看此教程

APP离线推送是业界一大难题,特别是Android机,国内手机厂商都阉割掉谷歌的推送服务,同时对后台进程严格限制,某些厂商甚至严格限制APP相互包活机制,所以难以保证用户能收到离线消息;
但APP离不开离线推送,像微信、QQ等大厂被国内各手机厂商加入系统级白名单,能保证实时到达率,对于小厂来说只能使用我说的办法。
教程要点:
1、APP需要离线打包;
2、集成个推(后公司要求改为集成了信鸽推送);
3、集成华为推送;
4、集成小米推送;
5、集成魅族推送;
此教程,需要有MUI开发经验,需要一点APP原生开发能力,不过按照我说的一步一来即可;

未完待续....

,若你急需此功能,加QQ:944515900,帮你解决,给个红包犒劳一下就行;

收起阅读 »

关于接触plus以来的一些经验

HTML5+

1.一定要android和IOS一起来测试,否则弄了半天,在一个运行的好好的,在另一个里便不行了,这样会浪费很多时间。
2.能在浏览器里弄得了的就在浏览器里搞,否则在调试的时候最大的一个特点就是在很多情况下不指明错误在哪儿。(在第几行)没有浏览器开发工具那种查看元素的功能。

  1. 很多API还不健全,特别是搞视频的时候,走了不少弯路,踩了不少坑。比如video, 缓存等等,很多东西都不能自定义。很多插件还亟待完善。
  2. 资料还不是很全,大部分时候搜的时候还是搜不到,论坛里很多时候没人搭理你。
继续阅读 »

1.一定要android和IOS一起来测试,否则弄了半天,在一个运行的好好的,在另一个里便不行了,这样会浪费很多时间。
2.能在浏览器里弄得了的就在浏览器里搞,否则在调试的时候最大的一个特点就是在很多情况下不指明错误在哪儿。(在第几行)没有浏览器开发工具那种查看元素的功能。

  1. 很多API还不健全,特别是搞视频的时候,走了不少弯路,踩了不少坑。比如video, 缓存等等,很多东西都不能自定义。很多插件还亟待完善。
  2. 资料还不是很全,大部分时候搜的时候还是搜不到,论坛里很多时候没人搭理你。
收起阅读 »

UniPush的推送到达率太低

unipush uniapp

最近我将APP的推送从个推改成了UniPush,可是我发现推送的到达率好低呀,我每次重启一下APP之后的第一条推送可能收到,后续的推送一条也收不到了。。。

其中java中的核心方法我贴出来了,各位大佬可以帮忙瞅瞅,有什么大问题吗?

/**  
     * intent模板  
     */  
    private static String intentTemplate = "intent:#Intent;action=android.intent.action.oppopush;component=%s/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=%s;S.content=%s;S.payload=%s;end";  

/**  
     * 获取管理APP Intent信息  
     * @param pushMessage 管理员推送消息  
     * @return intent字符串  
     */  
    private static String getManagerIntent(PushMessage pushMessage) {  
        return String.format(intentTemplate, managerAppProperties.getPackageName(), pushMessage.getTitle(), pushMessage.getContent(), ObjectUtils.toJson(pushMessage.getPayload()));  
    }  

    /**  
     * 获取司机APP Intent信息  
     * @param pushMessage 司机端推送的消息  
     * @return intent 字符串  
     */  
    private static String getDriverIntent(PushMessage pushMessage) {  
        return String.format(intentTemplate, driverAppProperties.getPackageName(), pushMessage.getTitle(), pushMessage.getContent(), ObjectUtils.toJson(pushMessage.getPayload()));  
    }  

   /**  
     * 创建透传模板  
     * @param pushMessage 透传消息对象  
     * @param manager 是否是管理员透传消息  
     * @return 透传模板  
     */  
    private static TransmissionTemplate createTransmissionTemplate(PushMessage pushMessage, boolean manager) {  
        // 创建模板  
        TransmissionTemplate template = new TransmissionTemplate();  
        if (manager) {  
            template.setAppId(managerAppProperties.getAppId());  
            template.setAppkey(managerAppProperties.getAppKey());  
        } else {  
            template.setAppId(driverAppProperties.getAppId());  
            template.setAppkey(driverAppProperties.getAppKey());  
        }  

        template.setTransmissionType(2);  
        template.setTransmissionContent(ObjectUtils.toJson(pushMessage));  

        Notify notify = new Notify();  
        notify.setTitle(pushMessage.getTitle());  
        notify.setContent(pushMessage.getContent());  
        notify.setIntent(manager ? getManagerIntent(pushMessage) : getDriverIntent(pushMessage));  
        notify.setType(GtReq.NotifyInfo.Type._intent);  

        template.set3rdNotifyInfo(notify);  
        return template;  
    }  

...
继续阅读 »

最近我将APP的推送从个推改成了UniPush,可是我发现推送的到达率好低呀,我每次重启一下APP之后的第一条推送可能收到,后续的推送一条也收不到了。。。

其中java中的核心方法我贴出来了,各位大佬可以帮忙瞅瞅,有什么大问题吗?

/**  
     * intent模板  
     */  
    private static String intentTemplate = "intent:#Intent;action=android.intent.action.oppopush;component=%s/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=%s;S.content=%s;S.payload=%s;end";  

/**  
     * 获取管理APP Intent信息  
     * @param pushMessage 管理员推送消息  
     * @return intent字符串  
     */  
    private static String getManagerIntent(PushMessage pushMessage) {  
        return String.format(intentTemplate, managerAppProperties.getPackageName(), pushMessage.getTitle(), pushMessage.getContent(), ObjectUtils.toJson(pushMessage.getPayload()));  
    }  

    /**  
     * 获取司机APP Intent信息  
     * @param pushMessage 司机端推送的消息  
     * @return intent 字符串  
     */  
    private static String getDriverIntent(PushMessage pushMessage) {  
        return String.format(intentTemplate, driverAppProperties.getPackageName(), pushMessage.getTitle(), pushMessage.getContent(), ObjectUtils.toJson(pushMessage.getPayload()));  
    }  

   /**  
     * 创建透传模板  
     * @param pushMessage 透传消息对象  
     * @param manager 是否是管理员透传消息  
     * @return 透传模板  
     */  
    private static TransmissionTemplate createTransmissionTemplate(PushMessage pushMessage, boolean manager) {  
        // 创建模板  
        TransmissionTemplate template = new TransmissionTemplate();  
        if (manager) {  
            template.setAppId(managerAppProperties.getAppId());  
            template.setAppkey(managerAppProperties.getAppKey());  
        } else {  
            template.setAppId(driverAppProperties.getAppId());  
            template.setAppkey(driverAppProperties.getAppKey());  
        }  

        template.setTransmissionType(2);  
        template.setTransmissionContent(ObjectUtils.toJson(pushMessage));  

        Notify notify = new Notify();  
        notify.setTitle(pushMessage.getTitle());  
        notify.setContent(pushMessage.getContent());  
        notify.setIntent(manager ? getManagerIntent(pushMessage) : getDriverIntent(pushMessage));  
        notify.setType(GtReq.NotifyInfo.Type._intent);  

        template.set3rdNotifyInfo(notify);  
        return template;  
    }  

...
收起阅读 »