HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

--

外包 招聘

--

--

打包的ipa在APP Store审核过程中因定位被退回的解决方法

审核 App打包 定位

iOS应用如果需要用到定位,正常情况下

plus.geolocation.getCurrentPosition((data)=>{},(error)=>{})

即可,这时会弹出提示框给用户选择是否允许使用定位功能。
但关键的地方就是,现在审核标准需要在APP里面说明为什么要获取定位,
因此就要在manifest.json里面的代码视图添加相关代码:

"plus": {  
  "distribute": {  
   "apple": {  
     "plistcmds": [  
         "Set :NSLocationAlwaysUsageDescription 我是经常要使用定位的原因描述",  
         "Set :NSLocationWhenInUseUsageDescription 我是需要使用定位的原因描述"  
      ]  
   }  
 }  
}
继续阅读 »

iOS应用如果需要用到定位,正常情况下

plus.geolocation.getCurrentPosition((data)=>{},(error)=>{})

即可,这时会弹出提示框给用户选择是否允许使用定位功能。
但关键的地方就是,现在审核标准需要在APP里面说明为什么要获取定位,
因此就要在manifest.json里面的代码视图添加相关代码:

"plus": {  
  "distribute": {  
   "apple": {  
     "plistcmds": [  
         "Set :NSLocationAlwaysUsageDescription 我是经常要使用定位的原因描述",  
         "Set :NSLocationWhenInUseUsageDescription 我是需要使用定位的原因描述"  
      ]  
   }  
 }  
}
收起阅读 »

【分享】5+App的中View

分享 titleNView nativeObj nativeUI maps map Webview

5+App 中的 View 大概可以分为:

  • DOM 也就是 HTML 的内容
  • Webview 做为 HTML 的容器
  • NView 原生 View
  • Map、Video 等原生的控件
  • NativeUI 系统原生界面

层级关系

默认的层级关系 DOM < Map = Webview < NView < NativeUI

  • DOM 的层级是最低的,因此经常出现某些 HTML 的内容被其它更高层级 View 遮挡的情况。
  • Map = Webview 其实不够严谨。原生控件创建后,会与当前 Webview 建立关联关系,可以简单理解为层级一致。
  • Webview < NView 是默认的情况,如果 NView 被 append 到 Webview 的话,NView 的层级则会跟随父 Webview。
  • NativeUI 系统原生界面的层级是最高的

下面通过一些示例,来验证一下这些层级关系。

示例

这里要先提一句,一个新的 Webview 创建并且显示,默认都会置于栈顶,也就是说会在当前所有 Webview 的最上层。

地图

  • NativeUI 弹出框在 Webview 与 Map 上层
  • 新的Webview 新开一个 Webview 会遮挡包含 Map 的 Webview。

NView

  • NView 默认情况下,层级是高于所有 Webview 的。
  • 不append 此时点击“新开窗口”或“返回”,会一直看到 NView 的存在。

  • append 此时 NView 作为 Webview 的一部分存在,层级与父 Webview 一致,点击“新开窗口”或“返回”不会再看到 NView 的存在。

  • NativeUI 弹出框始终会在 NView 上层

源码

示例的具体代码,见附件。

继续阅读 »

5+App 中的 View 大概可以分为:

  • DOM 也就是 HTML 的内容
  • Webview 做为 HTML 的容器
  • NView 原生 View
  • Map、Video 等原生的控件
  • NativeUI 系统原生界面

层级关系

默认的层级关系 DOM < Map = Webview < NView < NativeUI

  • DOM 的层级是最低的,因此经常出现某些 HTML 的内容被其它更高层级 View 遮挡的情况。
  • Map = Webview 其实不够严谨。原生控件创建后,会与当前 Webview 建立关联关系,可以简单理解为层级一致。
  • Webview < NView 是默认的情况,如果 NView 被 append 到 Webview 的话,NView 的层级则会跟随父 Webview。
  • NativeUI 系统原生界面的层级是最高的

下面通过一些示例,来验证一下这些层级关系。

示例

这里要先提一句,一个新的 Webview 创建并且显示,默认都会置于栈顶,也就是说会在当前所有 Webview 的最上层。

地图

  • NativeUI 弹出框在 Webview 与 Map 上层
  • 新的Webview 新开一个 Webview 会遮挡包含 Map 的 Webview。

NView

  • NView 默认情况下,层级是高于所有 Webview 的。
  • 不append 此时点击“新开窗口”或“返回”,会一直看到 NView 的存在。

  • append 此时 NView 作为 Webview 的一部分存在,层级与父 Webview 一致,点击“新开窗口”或“返回”不会再看到 NView 的存在。

  • NativeUI 弹出框始终会在 NView 上层

源码

示例的具体代码,见附件。

收起阅读 »

【5+】Webview页面之间的数据交流

JavaScript 跨页通信 Webview 技术分享

一个App,其中大部分是要对页面之间的数据进行交互。

123

碧如:A打开B页面,B页面执行一些代码,再通知回A页面。

这可能是h5+er们遇到最常见的一个场景了。

ok,我们将问题实例化:

A页面有个选择地区的按钮,需要打开B页面选择一个地区,然后获取到选取结果返回给A页面并展示。

我们看看用mui.fire怎么来实现这个功能

123

A页面

1

        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">A</h1>  
        </header>  
        <div class="mui-content">  
            <input type="text" readonly placeholder="未选择">  
            <button type="button" class="mui-btn mui-btn-blue">选取地区</button>  
        </div>  

        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            // 自定义监听select事件  
            document.addEventListener('select', function(e){  
                var text = e.detail.text;  
                document.querySelector("input").value = text;  
            });  
            // 按钮点击事件  
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){  
                // 打开B页面,选取一个结果  
                mui.openWindow('B.html');  
            });  
        </script>

B页面

2

        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">B</h1>  
        </header>  
        <div class="mui-content">  
            <ul class="mui-table-view">  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        上海  
                    </a>  
                </li>  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        深圳  
                    </a>  
                </li>  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        北京  
                    </a>  
                </li>  
            </ul>  
        </div>  

        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui('ul').on('tap', 'li', function() {  
                // 获取当前选择的内容  
                var text = this.innerText;  
                // 通知上个页面  
                var w = plus.webview.currentWebview();  
                var opener = w.opener();  
                mui.fire(opener, "select",{  
                    text: text  
                });  
                // 关闭本页面  
                w.close();  
            });

真机调试一下,o98k。

3

但是!我个人还是建议脱离mui.js来实现这个功能

4

可以借用咱们之前文章里面的讲过的,利用webview对象的evalJS方法

【5+】跨webview多页面 触发事件(一)
【5+】跨webview多页面 触发事件(一)

感觉用Broadcast.js有点小题大做

5

那咱们就写一个类似Android中的onActivityResult和setResult方法

新建一个app.js,作为一个自己的插件,里面实现两个方法 onActivityResult 和 setResult


(function(app){  

    /**  
     * 打开一个页面  
     * @param {String} url 页面路径  
     * @param {String} id 页面id  
     * @param {Object} ex 参数  
     * @param {Function} callback   
     */  
    app.onActivityResult = function(url, id, ex, callback){  

    };  

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data){  

    };  

}(window.app || (window.app = {})));  

我们一步步来,先看看setResult如何触发上个页面的函数

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data){  
        // 获取当前webview  
        var indexW = plus.webview.currentWebview();  
        // 获取创建者的webview  
        var opener = indexW.opener();  
        // 执行js字符串  
        opener.evalJS();// ??????  
    };

卧槽,那么,问题来了,evalJS该执行什么呢?

如果我在A页面的window对象下定一个函数

window.test = function(data){  
    alert(JSON.stringify(data));  
}

那么,我们在evalJS里面就该这么写

        // 执行js字符串  
        var jsstr = "window.test && window.test(" + JSON.stringify(data) + ")";  
        opener.evalJS(jsstr); 

好吧,考虑到一个页面可能通过这个方式打开多个页面,那么我们这个test函数就得改一个不重复唯一的名称,并且定义放到onActivityResult方法里面

    var _id = 0,  
        _tempName = '',  
        ow,cw;  

        /**  
         * 打开一个页面  
         * @param {String} url 页面路径  
         * @param {String} id 页面id  
         * @param {Object} ex 参数  
         * @param {Function} callback   
         */  
        app.onActivityResult = function(url, id, ex, callback) {  

            // 生成唯一回调函数名称  
            _tempName = 'APP_RESULT_FUN_' + _id++;  
            // 定义函数  
            window[_tempName] = function(data){  
                // 执行自定义回调  
                callback(data);  
            };  
            // 传递函数名称到目标页面  
            ex.callbackName = _tempName;  

            // 显示菊花  
            cw = plus.nativeUI.showWaiting();  

            // 创建目标页面   
            ow = plus.webview.create(url, id, {  
                render: "always"  
            }, ex);  
            // title更新时显示 页面  
            ow.addEventListener('titleUpdate', function(){  
                // 关闭菊花  
                cw && (cw.close(),cw = null);  
                // 显示页面  
                ow.show('pop-in');  
            });  
            // 页面关闭时,注销window下此次事件  
            ow.addEventListener('close', function(){  
                                setTimeout(function(){  
                                        window[_tempName] = null;  
                                });  

            });  

        };

生成特殊一个函数,并把函数名通过extras的方式传参到目标页面,
相应的,setResult方法也需要少许更改

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data) {  
        // 获取当前webview  
        var indexW = plus.webview.currentWebview();  
        // js字符串  
        var jsstr = "";  
        // 如果存在自定义回调函数名  
        if(indexW.callbackName){  
            // 拼接js字符串  
            jsstr = "window." + indexW.callbackName;  
            jsstr = jsstr + "&&" + jsstr + "(" + JSON.stringify(data) + ")";  
            // 执行  
            indexW.opener().evalJS(jsstr);  
        }  
        // 返回当前页面  
        return indexW;  
    };

试试引用后在AB页面测试一下

            // A页面 按钮点击事件  
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){  
                // 打开B页面,选取一个结果  
                app.onActivityResult('B.html', 'B', {}, function(data){  
                    // 修改内容  
                    document.querySelector("input").value = data.text;  
                });  
            });  

            // B页面 选项点击事件  
            mui('ul').on('tap', 'li', function() {  
                // 获取当前选择的内容  
                var text = this.innerText;  
                // 通知上个页面 并关闭本页面  
                app.setResult({  
                    text: text  
                }).close();  
            });

卧槽666。

class Man{  
    constructor(){  
        this.name = 'newsning'  
    }  
    say(){  
        console.log('天行健, 君子以自强不息. ')  
    }  
}
继续阅读 »

一个App,其中大部分是要对页面之间的数据进行交互。

123

碧如:A打开B页面,B页面执行一些代码,再通知回A页面。

这可能是h5+er们遇到最常见的一个场景了。

ok,我们将问题实例化:

A页面有个选择地区的按钮,需要打开B页面选择一个地区,然后获取到选取结果返回给A页面并展示。

我们看看用mui.fire怎么来实现这个功能

123

A页面

1

        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">A</h1>  
        </header>  
        <div class="mui-content">  
            <input type="text" readonly placeholder="未选择">  
            <button type="button" class="mui-btn mui-btn-blue">选取地区</button>  
        </div>  

        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            // 自定义监听select事件  
            document.addEventListener('select', function(e){  
                var text = e.detail.text;  
                document.querySelector("input").value = text;  
            });  
            // 按钮点击事件  
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){  
                // 打开B页面,选取一个结果  
                mui.openWindow('B.html');  
            });  
        </script>

B页面

2

        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">B</h1>  
        </header>  
        <div class="mui-content">  
            <ul class="mui-table-view">  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        上海  
                    </a>  
                </li>  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        深圳  
                    </a>  
                </li>  
                <li class="mui-table-view-cell">  
                    <a class="mui-navigate-right">  
                        北京  
                    </a>  
                </li>  
            </ul>  
        </div>  

        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui('ul').on('tap', 'li', function() {  
                // 获取当前选择的内容  
                var text = this.innerText;  
                // 通知上个页面  
                var w = plus.webview.currentWebview();  
                var opener = w.opener();  
                mui.fire(opener, "select",{  
                    text: text  
                });  
                // 关闭本页面  
                w.close();  
            });

真机调试一下,o98k。

3

但是!我个人还是建议脱离mui.js来实现这个功能

4

可以借用咱们之前文章里面的讲过的,利用webview对象的evalJS方法

【5+】跨webview多页面 触发事件(一)
【5+】跨webview多页面 触发事件(一)

感觉用Broadcast.js有点小题大做

5

那咱们就写一个类似Android中的onActivityResult和setResult方法

新建一个app.js,作为一个自己的插件,里面实现两个方法 onActivityResult 和 setResult


(function(app){  

    /**  
     * 打开一个页面  
     * @param {String} url 页面路径  
     * @param {String} id 页面id  
     * @param {Object} ex 参数  
     * @param {Function} callback   
     */  
    app.onActivityResult = function(url, id, ex, callback){  

    };  

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data){  

    };  

}(window.app || (window.app = {})));  

我们一步步来,先看看setResult如何触发上个页面的函数

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data){  
        // 获取当前webview  
        var indexW = plus.webview.currentWebview();  
        // 获取创建者的webview  
        var opener = indexW.opener();  
        // 执行js字符串  
        opener.evalJS();// ??????  
    };

卧槽,那么,问题来了,evalJS该执行什么呢?

如果我在A页面的window对象下定一个函数

window.test = function(data){  
    alert(JSON.stringify(data));  
}

那么,我们在evalJS里面就该这么写

        // 执行js字符串  
        var jsstr = "window.test && window.test(" + JSON.stringify(data) + ")";  
        opener.evalJS(jsstr); 

好吧,考虑到一个页面可能通过这个方式打开多个页面,那么我们这个test函数就得改一个不重复唯一的名称,并且定义放到onActivityResult方法里面

    var _id = 0,  
        _tempName = '',  
        ow,cw;  

        /**  
         * 打开一个页面  
         * @param {String} url 页面路径  
         * @param {String} id 页面id  
         * @param {Object} ex 参数  
         * @param {Function} callback   
         */  
        app.onActivityResult = function(url, id, ex, callback) {  

            // 生成唯一回调函数名称  
            _tempName = 'APP_RESULT_FUN_' + _id++;  
            // 定义函数  
            window[_tempName] = function(data){  
                // 执行自定义回调  
                callback(data);  
            };  
            // 传递函数名称到目标页面  
            ex.callbackName = _tempName;  

            // 显示菊花  
            cw = plus.nativeUI.showWaiting();  

            // 创建目标页面   
            ow = plus.webview.create(url, id, {  
                render: "always"  
            }, ex);  
            // title更新时显示 页面  
            ow.addEventListener('titleUpdate', function(){  
                // 关闭菊花  
                cw && (cw.close(),cw = null);  
                // 显示页面  
                ow.show('pop-in');  
            });  
            // 页面关闭时,注销window下此次事件  
            ow.addEventListener('close', function(){  
                                setTimeout(function(){  
                                        window[_tempName] = null;  
                                });  

            });  

        };

生成特殊一个函数,并把函数名通过extras的方式传参到目标页面,
相应的,setResult方法也需要少许更改

    /**  
     * 返回创建者页面数据  
     * @param {Object} data 需要返回的数据  
     * @return {Webview} w 当前webview  
     */  
    app.setResult = function(data) {  
        // 获取当前webview  
        var indexW = plus.webview.currentWebview();  
        // js字符串  
        var jsstr = "";  
        // 如果存在自定义回调函数名  
        if(indexW.callbackName){  
            // 拼接js字符串  
            jsstr = "window." + indexW.callbackName;  
            jsstr = jsstr + "&&" + jsstr + "(" + JSON.stringify(data) + ")";  
            // 执行  
            indexW.opener().evalJS(jsstr);  
        }  
        // 返回当前页面  
        return indexW;  
    };

试试引用后在AB页面测试一下

            // A页面 按钮点击事件  
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){  
                // 打开B页面,选取一个结果  
                app.onActivityResult('B.html', 'B', {}, function(data){  
                    // 修改内容  
                    document.querySelector("input").value = data.text;  
                });  
            });  

            // B页面 选项点击事件  
            mui('ul').on('tap', 'li', function() {  
                // 获取当前选择的内容  
                var text = this.innerText;  
                // 通知上个页面 并关闭本页面  
                app.setResult({  
                    text: text  
                }).close();  
            });

卧槽666。

class Man{  
    constructor(){  
        this.name = 'newsning'  
    }  
    say(){  
        console.log('天行健, 君子以自强不息. ')  
    }  
}
收起阅读 »

点击li跳转时总跳转至第一个li的页面。而alert显示的是正确的innertext

js
var obj_lis = document.getElementById("my_list_movie").getElementsByTagName("li");  
            for(i = 0; i < obj_lis.length; i++) {  
                obj_lis[i].onclick = function() {  
                    if(this.innerHTML.indexOf("电影票订单")) {  
                        window.location.href = "ticket_order.html";  
                        alert(this.innerHTML);  
                    } else if(this.innerHTML.indexOf("代金优惠卷")) {  
                        window.location.href = "coupons.html";  
                        alert(this.innerHTML);  
                    } else if(this.innerHTML.indexOf("收藏的电影")) {  
                        window.location.href = "favorite_movie.html";  
                        alert(this.innerHTML);  
                    }  
                }  
            }
继续阅读 »
var obj_lis = document.getElementById("my_list_movie").getElementsByTagName("li");  
            for(i = 0; i < obj_lis.length; i++) {  
                obj_lis[i].onclick = function() {  
                    if(this.innerHTML.indexOf("电影票订单")) {  
                        window.location.href = "ticket_order.html";  
                        alert(this.innerHTML);  
                    } else if(this.innerHTML.indexOf("代金优惠卷")) {  
                        window.location.href = "coupons.html";  
                        alert(this.innerHTML);  
                    } else if(this.innerHTML.indexOf("收藏的电影")) {  
                        window.location.href = "favorite_movie.html";  
                        alert(this.innerHTML);  
                    }  
                }  
            }
收起阅读 »

vue2.x引入mui的开源项目源码+案例公开,没有过多的业务逻辑,刚写的项目,希望有好的commit提交过来整理好项目

mui h5+ 案例 源码分享

项目地址:https://github.com/wuhou123/mui-vue2
下载app可以查看我的-我的足迹用到h5+和原生定位功能
也有关于mui常见问题文档
如果有问题提issues吧

继续阅读 »

项目地址:https://github.com/wuhou123/mui-vue2
下载app可以查看我的-我的足迹用到h5+和原生定位功能
也有关于mui常见问题文档
如果有问题提issues吧

收起阅读 »

IOS系统执行map = new plus.maps.Map('mymap');

HTML5+

IOS系统离线打包后:页面初始化时,执行 new plus.maps.Map('')
页面弹出
配置的百度地图密钥(appkey)校验失败[230],参考http://ask.dcloub.net.cn/article/29
百度地图配置的安全码是对的,云打包就没问题,这是什么问题?

继续阅读 »

IOS系统离线打包后:页面初始化时,执行 new plus.maps.Map('')
页面弹出
配置的百度地图密钥(appkey)校验失败[230],参考http://ask.dcloub.net.cn/article/29
百度地图配置的安全码是对的,云打包就没问题,这是什么问题?

收起阅读 »

css常用知识点

css

解决img标签与p标签之间有空隙的问题
1.将img设置为block: img{display:block}

  1. 设置img的竖直对其方式:vertical-align: bottom;
  2. 定义容器里的字体大小为0。
    div{
      width:110px;
      border:1px solid #000000;
      font-size:0px;
    }
    css实现图片元素水平垂直居中
    样式
    //style  
    .outer{  
     width: 500px;  
     height: 200px;  
     line-height: 200px;  
     text-align: center;  
     border: green solid 5px;  
    }  
    .inner{  
    display: inline-block;  
    vertical-algin: middle;  
    }

    html

    <div class='outer'>  
    <img src="https://www.baidu.com/img/baidu_jgylogo3.gif">  
    </div>

.one {
position:absolute;
width200px;
height:200px;
top:50%;
left:50%;
margin-top:-100px;
margin-left:-100px;
background:red;
}

.two{
position:fixed;
width:180px;
height:180px;
top:50%;
left:50%;
margin-top:-90px;
margin-left:-90px;
background:orange;
}

.three{
position:fixed; width:160px; height:160px; top:0; right:0; bottom:0; left:0; margin:auto; background:pink;
}
.four{ position:absolute; width:140px; height:140px; top:0; right:0; bottom:0; left:0; margin:auto; background:black;}

css实现单行、多行文本溢出显示省略号
单行文本的移除显示省略号用text-overflow:ellipsis属性,还需要加宽度width属性来兼容部分浏览器。
实现方法:

overflow:hidden;  
white-spacen:nowrap;  
text-overflow:ellipsis;

1.使用overflow:hidden把超出的内容进行隐藏;

  1. 然后使用white-space:nowrap设置内容不换行;
  2. 最后使用text-overflow:ellipsis设置超出内容为省略号

但是这个属性只支持单行文本的溢出显示省略号。
实现多行文本溢出显示省略号,如下。

display:-webkit-box;  
-webkit-box-orient:vertical;  
-webkit-line-clamp:2;  
overflow:hidden;

因为使用了webkit的css扩展属性,该方法适用于webkit浏览器及移动端;
注:
1.-webkit-line-clamp用来限制在一个块元素显示的文本的行数。为了实现该效果,它需要组合其他的webkit属性。常见结合属性:

  1. display:-webkit-box;必须结合的属性,将对象作为弹性伸缩盒子模型显示。
  2. -webkit-box-orient必须结合的属性,设置或检索伸缩盒对象的子元素的排列方式。
    实现方法:
    p{position:relative;line-height:20px;max-height:40px;overflow:hidden;}  
    p::after{content:"...";position:absolute;bottom:0;right:0;padding-left:40px;  
    background: line-gradient(to right,transparent,#fff 55%);  
    background: -webkit-linear-gradient(left, transparent, #fff 55%);  
    background: -o-linear-gradient(right, transparent, #fff 55%);  
    background: -moz-linear-gradient(right, transparent, #fff 55%);  
    }

    该方法使用范围广,但文字未超出行的情况下也会出现省略号,可结合js优化该方法。
    注:
    1.将height设置为line-height的整倍数,防止超出的文字露出。

  3. 给p::after添加背景可避免文字只显示一半。
    3.由于ie6-7不显示content内容,所以要添加标签兼容ie6-7(如:<span>…<span/>);兼容ie8需要将::after替换成:after

css3中的transform对行内元素(inline)无效,查资料后发现,transform适用于:所有块级元素及某些内联元素
相关链接:http://www.css88.com/book/css/properties/transform/transform.htm

继续阅读 »

解决img标签与p标签之间有空隙的问题
1.将img设置为block: img{display:block}

  1. 设置img的竖直对其方式:vertical-align: bottom;
  2. 定义容器里的字体大小为0。
    div{
      width:110px;
      border:1px solid #000000;
      font-size:0px;
    }
    css实现图片元素水平垂直居中
    样式
    //style  
    .outer{  
     width: 500px;  
     height: 200px;  
     line-height: 200px;  
     text-align: center;  
     border: green solid 5px;  
    }  
    .inner{  
    display: inline-block;  
    vertical-algin: middle;  
    }

    html

    <div class='outer'>  
    <img src="https://www.baidu.com/img/baidu_jgylogo3.gif">  
    </div>

.one {
position:absolute;
width200px;
height:200px;
top:50%;
left:50%;
margin-top:-100px;
margin-left:-100px;
background:red;
}

.two{
position:fixed;
width:180px;
height:180px;
top:50%;
left:50%;
margin-top:-90px;
margin-left:-90px;
background:orange;
}

.three{
position:fixed; width:160px; height:160px; top:0; right:0; bottom:0; left:0; margin:auto; background:pink;
}
.four{ position:absolute; width:140px; height:140px; top:0; right:0; bottom:0; left:0; margin:auto; background:black;}

css实现单行、多行文本溢出显示省略号
单行文本的移除显示省略号用text-overflow:ellipsis属性,还需要加宽度width属性来兼容部分浏览器。
实现方法:

overflow:hidden;  
white-spacen:nowrap;  
text-overflow:ellipsis;

1.使用overflow:hidden把超出的内容进行隐藏;

  1. 然后使用white-space:nowrap设置内容不换行;
  2. 最后使用text-overflow:ellipsis设置超出内容为省略号

但是这个属性只支持单行文本的溢出显示省略号。
实现多行文本溢出显示省略号,如下。

display:-webkit-box;  
-webkit-box-orient:vertical;  
-webkit-line-clamp:2;  
overflow:hidden;

因为使用了webkit的css扩展属性,该方法适用于webkit浏览器及移动端;
注:
1.-webkit-line-clamp用来限制在一个块元素显示的文本的行数。为了实现该效果,它需要组合其他的webkit属性。常见结合属性:

  1. display:-webkit-box;必须结合的属性,将对象作为弹性伸缩盒子模型显示。
  2. -webkit-box-orient必须结合的属性,设置或检索伸缩盒对象的子元素的排列方式。
    实现方法:
    p{position:relative;line-height:20px;max-height:40px;overflow:hidden;}  
    p::after{content:"...";position:absolute;bottom:0;right:0;padding-left:40px;  
    background: line-gradient(to right,transparent,#fff 55%);  
    background: -webkit-linear-gradient(left, transparent, #fff 55%);  
    background: -o-linear-gradient(right, transparent, #fff 55%);  
    background: -moz-linear-gradient(right, transparent, #fff 55%);  
    }

    该方法使用范围广,但文字未超出行的情况下也会出现省略号,可结合js优化该方法。
    注:
    1.将height设置为line-height的整倍数,防止超出的文字露出。

  3. 给p::after添加背景可避免文字只显示一半。
    3.由于ie6-7不显示content内容,所以要添加标签兼容ie6-7(如:<span>…<span/>);兼容ie8需要将::after替换成:after

css3中的transform对行内元素(inline)无效,查资料后发现,transform适用于:所有块级元素及某些内联元素
相关链接:http://www.css88.com/book/css/properties/transform/transform.htm

收起阅读 »

cookie和session有什么区别?

session

1.由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是session。典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的session,用于标识这个用户,并且跟踪用户,这样才知道购物车里有几本书这个session是保存在服务端的,有一个唯一标识。在服务端保存session的方法很多,内存、数据库、文件都有。集群的时候也要考虑session的转移,在大型的网站,一般会有专门的session服务器集群,用来保存用户会话,这个时候session信息都是放在内存的,使用一些缓存服务比如Mecached之类的来放session。

  1. 服务端是如何识别特定的客户的?这个时候cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用Cookie来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在Cookie里面记录一个Seeion ID,以后每次请求都会把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了Cookie怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被加上一个诸如sid=XXX这样的参数,服务端据此来识别用户。
  2. cookie信息可以写到cookie里面,访问网站的时候,网站页面的脚本客户已读取这个信息,就自动帮你把用户名填了,方便用户
    session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存咋集群、数据库、文件中;
    cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是是实现session的一种方式。

不要混淆session和session实现。
本来session是一个抽象的概念,开发者为了实现中断和继续等操作,将user agent和server之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是session的概念。
而cookie是一个实际存在的东西,http协议中定义在header中的字段。可以认为是session的一种后端无状态实现。
而我们今天常说的“session”,是为了绕开cookie的各种限制,通常借助cookie本身和后端存储实现的,一种更高级的会话状态实现。
所以cookie和session,你可以认为是同一层次的概念,也可以认为是不同层次的概念。具体到实现,session因为session id的存在,通常要借助cookie实现,但这并非必要,只能说是通用性较好的一种实现方案。

1.session在服务端,cookie在客户端(浏览器)

  1. session默认被存在服务器的一个文件里(不是内存)
  2. session的运行依赖session id,而session id是存在cookie中的,也就是说如果浏览器禁用了cookie,同时session也会失效(可以通过其它方式实现,如在url中传递session_id)
  3. session可以放在文件、数据库、或内存中的都可以。
  4. 用户验证这种场合一般都会用session
    因此,维持一个会话的核心就是客户端的唯一标识,即session_id
继续阅读 »

1.由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是session。典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的session,用于标识这个用户,并且跟踪用户,这样才知道购物车里有几本书这个session是保存在服务端的,有一个唯一标识。在服务端保存session的方法很多,内存、数据库、文件都有。集群的时候也要考虑session的转移,在大型的网站,一般会有专门的session服务器集群,用来保存用户会话,这个时候session信息都是放在内存的,使用一些缓存服务比如Mecached之类的来放session。

  1. 服务端是如何识别特定的客户的?这个时候cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用Cookie来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在Cookie里面记录一个Seeion ID,以后每次请求都会把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了Cookie怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被加上一个诸如sid=XXX这样的参数,服务端据此来识别用户。
  2. cookie信息可以写到cookie里面,访问网站的时候,网站页面的脚本客户已读取这个信息,就自动帮你把用户名填了,方便用户
    session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存咋集群、数据库、文件中;
    cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是是实现session的一种方式。

不要混淆session和session实现。
本来session是一个抽象的概念,开发者为了实现中断和继续等操作,将user agent和server之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是session的概念。
而cookie是一个实际存在的东西,http协议中定义在header中的字段。可以认为是session的一种后端无状态实现。
而我们今天常说的“session”,是为了绕开cookie的各种限制,通常借助cookie本身和后端存储实现的,一种更高级的会话状态实现。
所以cookie和session,你可以认为是同一层次的概念,也可以认为是不同层次的概念。具体到实现,session因为session id的存在,通常要借助cookie实现,但这并非必要,只能说是通用性较好的一种实现方案。

1.session在服务端,cookie在客户端(浏览器)

  1. session默认被存在服务器的一个文件里(不是内存)
  2. session的运行依赖session id,而session id是存在cookie中的,也就是说如果浏览器禁用了cookie,同时session也会失效(可以通过其它方式实现,如在url中传递session_id)
  3. session可以放在文件、数据库、或内存中的都可以。
  4. 用户验证这种场合一般都会用session
    因此,维持一个会话的核心就是客户端的唯一标识,即session_id
收起阅读 »

关于打包正式版APP

云端打包发布常见问题

一定要用最新版。否则图标弄死都是Hbuilder那个图标。
坑了我一个月,也是醉了。都不强制更新下app。找资料也找不到。

一定要用最新版。否则图标弄死都是Hbuilder那个图标。
坑了我一个月,也是醉了。都不强制更新下app。找资料也找不到。

上传图片和压缩

压缩图片
分享自己写的一个上传图片并压缩的方法  
element是点击的元素  
defaultPic默认图片的名称  
defaultPath默认图片的路径  
category是我写的一个分类  
overwrite是否覆盖压缩 默认覆盖压缩  
quality压缩的大小 默认百分之二十  
overWriteName 图片压缩后的名称  
<div class="uploadPhotoItem">  
                    <img class="pictureUpload pictures" src="../../../images/pic_morentu.jpg">  
                    <span>照片</span>  
                </div>  
//获取上传图片元素  
  var pictureUploads = document.getElementsByClassName('pictureUpload');  
for (var i = 0; i < pictureUploads.length; i++) {  
      utilsJs.uploadPictures({  
        element: pictureUploads[i],  
        defaultPic: 'pic_morentu',  
        defaultPath: '../../images/pic_morentu.jpg',  
        category: 'order',  
        onSuccess: function () {  

        },  
        onFailed: function () {  
          ApiConfig.staticShowToast('图片上传失败');  
        }  
      })  
    }  
Utils.prototype.uploadPictures = function (options) {  
  var _this = this;  
  options = options || {};  
  var element = options.element;  
  var quality = options.quality;  
  var category = options.category;  
  var overwrite = options.overwrite;  
  var defaultPic = options.defaultPic;  
  var defaultPath = options.defaultPath;  
  var overWriteName = options.overWriteName;  
  if (element) {  
    element.addEventListener('tap', function () {  
      _this.selectUploadWay({  
        element: element,  
        quality: quality,  
        category: category,  
        overwrite: overwrite,  
        defaultPic: defaultPic,  
        defaultPath: defaultPath,  
        overWriteName: overWriteName,  
        onSuccess: function (responseJson) {  
          options.onSuccess && options.onSuccess(responseJson);  
        },  
        onFailed: function (errorJson) {  
          options.onFailed && options.onFailed(errorJson);  
        },  
        onCompleted: function () {  
          options.onCompleted && options.onCompleted();  
        }  
      });  
    })  
  }  
}  
Utils.prototype.selectUploadWay = function (options) {  
  options = options || {};  
  var _this = this;  
  var element = options.element;  
  var defaultPic = options.defaultPic;  
  var defaultPath = options.defaultPath;  
  var overWriteName = options.overWriteName;  
  var bts = [{  
    title: '相册'  
  }, {  
    title: '拍照'  
  }, {  
    title: '删除'  
  }];  
  plus.nativeUI.actionSheet({  
      cancel: "取消",  
      buttons: bts  
    },  
    function (e) {  
      var i = e.index;  
      switch (i) {  
        case 1:  
          // 拍照添加文件  
          plus.gallery.pick(function (path) {  
            _this.uploadPictureHandle({  
              src: path,  
              dst: options.dst,  
              quality: options.quality,  
              element: options.element,  
              category: options.category,  
              overwrite: options.overwrite,  
              overWriteName: overWriteName,  
              onSuccess: function (responseJson) {  
                options.onSuccess && options.onSuccess(responseJson);  
              },  
              onFailed: function (errorJson) {  
                options.onFailed && options.onFailed(errorJson);  
              },  
              onCompleted: function () {  
                options.onCompleted && options.onCompleted();  
              }  
            })  
          });  
          break;  
        case 2:  
          // 从相册添加文件  
          plus.camera.getCamera().captureImage(function (path) {  
            _this.uploadPictureHandle({  
              src: path,  
              dst: options.dst,  
              quality: options.quality,  
              element: options.element,  
              category: options.category,  
              overwrite: options.overwrite,  
              overWriteName: overWriteName,  
              onSuccess: function (responseJson) {  
                options.onSuccess && options.onSuccess(responseJson);  
              },  
              onFailed: function (errorJson) {  
                options.onFailed && options.onFailed(errorJson);  
              },  
              onCompleted: function () {  
                options.onCompleted && options.onCompleted();  
              }  
            })  
          });  
          break;  
        case 3:  
          if (element.src.indexOf(defaultPic) >= 0) {  
            ApiConfig.staticShowToast('当前未上传图片,无法删除');  
          } else {  
            element.src = defaultPath;  
          }  
          break;  
        default:  
          break;  
      }  
    }  
  );  
}  
Utils.prototype.uploadPictureHandle = function (options) {  
  options = options || {};  
  var element = options.element;  
  var overWriteName = options.overWriteName;  
  if (!options.overwrite) {  
    overWriteName = '_doc/default.jpg';  
  }  
  plus.zip.compressImage({  
      src: options.src,  
      dst: overWriteName,  
      quality: options.quality || 20,  
      overwrite: options.overwrite || true  
    },  
    function (event) {  
      dpHttp.upLoadPictureHttp({  
        files: event.target,  
        category: options.category,  
        onSuccess: function (responseJson) {  
          element.src = responseJson.url;  
          options.onSuccess && options.onSuccess(responseJson);  
        },  
        onFailed: function (errorJson) {  
          options.onFailed && options.onFailed(errorJson);  
        },  
        onCompleted: function () {  
          options.onCompleted && options.onCompleted();  
        }  
      });  
    },  
    function (error) {  
      options.onFailed && options.onFailed(error);  
      console.log(JSON.stringify(error));  
    }  
  );  
}  
HttpUtils.prototype.upLoadFile = function (options) {  
  var wt = plus.nativeUI.showWaiting();  
  options = options || {};  
  var responseJson = null;  
  var postParams = options.postParams;  
  var postFilesMap = options.postFilesMap;  

  ApiConfig.staticIsDebug('upLoadFile', options.url);  
  var task = plus.uploader.createUpload(options.url, {  
    method: "POST",  
    priority: 100  
  }, function (t, status) {  
    if (status == 200) {  
      try {  
        wt.close();  
        responseJson = JSON.parse(t.responseText);  
        if (responseJson.rt) {  
          ApiConfig.staticIsDebug('responseJson', responseJson, 1);  
          options.onSuccess && options.onSuccess(responseJson);  
        } else {  
          ApiConfig.staticIsDebug('errorJson', responseJson, 1);  
          options.onFailed && options.onFailed(responseJson);  
        }  
      } catch (e) {  
        wt.close();  
        ApiConfig.staticIsDebug('error', e);  
        ApiConfig.staticIsDebug('errorJson', xhr.responseText);  
        options.onFailed && options.onFailed(responseJson);  
      }  
    } else {  
      wt.close();  
      ApiConfig.staticIsDebug('errorJson', responseJson, 1);  
      options.onFailed && options.onFailed(responseJson);  
    }  
  });  
  //task.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
  var keys = postFilesMap.keys();  
  task.addFile(postFilesMap.get(keys[0]), {  
    key: keys[0]  
  });  
  if (postParams) {  
    var paramsKeys = postParams.keys();  
    if (paramsKeys.length > 1) {  
      paramsKeys.forEach(function (key) {  
        task.addData(key, postParams.get(key));  
      })  
    } else {  
      task.addData(paramsKeys[0], postParams.get(paramsKeys[0]));  
    }  
  }  
  task.start();  
}
继续阅读 »
分享自己写的一个上传图片并压缩的方法  
element是点击的元素  
defaultPic默认图片的名称  
defaultPath默认图片的路径  
category是我写的一个分类  
overwrite是否覆盖压缩 默认覆盖压缩  
quality压缩的大小 默认百分之二十  
overWriteName 图片压缩后的名称  
<div class="uploadPhotoItem">  
                    <img class="pictureUpload pictures" src="../../../images/pic_morentu.jpg">  
                    <span>照片</span>  
                </div>  
//获取上传图片元素  
  var pictureUploads = document.getElementsByClassName('pictureUpload');  
for (var i = 0; i < pictureUploads.length; i++) {  
      utilsJs.uploadPictures({  
        element: pictureUploads[i],  
        defaultPic: 'pic_morentu',  
        defaultPath: '../../images/pic_morentu.jpg',  
        category: 'order',  
        onSuccess: function () {  

        },  
        onFailed: function () {  
          ApiConfig.staticShowToast('图片上传失败');  
        }  
      })  
    }  
Utils.prototype.uploadPictures = function (options) {  
  var _this = this;  
  options = options || {};  
  var element = options.element;  
  var quality = options.quality;  
  var category = options.category;  
  var overwrite = options.overwrite;  
  var defaultPic = options.defaultPic;  
  var defaultPath = options.defaultPath;  
  var overWriteName = options.overWriteName;  
  if (element) {  
    element.addEventListener('tap', function () {  
      _this.selectUploadWay({  
        element: element,  
        quality: quality,  
        category: category,  
        overwrite: overwrite,  
        defaultPic: defaultPic,  
        defaultPath: defaultPath,  
        overWriteName: overWriteName,  
        onSuccess: function (responseJson) {  
          options.onSuccess && options.onSuccess(responseJson);  
        },  
        onFailed: function (errorJson) {  
          options.onFailed && options.onFailed(errorJson);  
        },  
        onCompleted: function () {  
          options.onCompleted && options.onCompleted();  
        }  
      });  
    })  
  }  
}  
Utils.prototype.selectUploadWay = function (options) {  
  options = options || {};  
  var _this = this;  
  var element = options.element;  
  var defaultPic = options.defaultPic;  
  var defaultPath = options.defaultPath;  
  var overWriteName = options.overWriteName;  
  var bts = [{  
    title: '相册'  
  }, {  
    title: '拍照'  
  }, {  
    title: '删除'  
  }];  
  plus.nativeUI.actionSheet({  
      cancel: "取消",  
      buttons: bts  
    },  
    function (e) {  
      var i = e.index;  
      switch (i) {  
        case 1:  
          // 拍照添加文件  
          plus.gallery.pick(function (path) {  
            _this.uploadPictureHandle({  
              src: path,  
              dst: options.dst,  
              quality: options.quality,  
              element: options.element,  
              category: options.category,  
              overwrite: options.overwrite,  
              overWriteName: overWriteName,  
              onSuccess: function (responseJson) {  
                options.onSuccess && options.onSuccess(responseJson);  
              },  
              onFailed: function (errorJson) {  
                options.onFailed && options.onFailed(errorJson);  
              },  
              onCompleted: function () {  
                options.onCompleted && options.onCompleted();  
              }  
            })  
          });  
          break;  
        case 2:  
          // 从相册添加文件  
          plus.camera.getCamera().captureImage(function (path) {  
            _this.uploadPictureHandle({  
              src: path,  
              dst: options.dst,  
              quality: options.quality,  
              element: options.element,  
              category: options.category,  
              overwrite: options.overwrite,  
              overWriteName: overWriteName,  
              onSuccess: function (responseJson) {  
                options.onSuccess && options.onSuccess(responseJson);  
              },  
              onFailed: function (errorJson) {  
                options.onFailed && options.onFailed(errorJson);  
              },  
              onCompleted: function () {  
                options.onCompleted && options.onCompleted();  
              }  
            })  
          });  
          break;  
        case 3:  
          if (element.src.indexOf(defaultPic) >= 0) {  
            ApiConfig.staticShowToast('当前未上传图片,无法删除');  
          } else {  
            element.src = defaultPath;  
          }  
          break;  
        default:  
          break;  
      }  
    }  
  );  
}  
Utils.prototype.uploadPictureHandle = function (options) {  
  options = options || {};  
  var element = options.element;  
  var overWriteName = options.overWriteName;  
  if (!options.overwrite) {  
    overWriteName = '_doc/default.jpg';  
  }  
  plus.zip.compressImage({  
      src: options.src,  
      dst: overWriteName,  
      quality: options.quality || 20,  
      overwrite: options.overwrite || true  
    },  
    function (event) {  
      dpHttp.upLoadPictureHttp({  
        files: event.target,  
        category: options.category,  
        onSuccess: function (responseJson) {  
          element.src = responseJson.url;  
          options.onSuccess && options.onSuccess(responseJson);  
        },  
        onFailed: function (errorJson) {  
          options.onFailed && options.onFailed(errorJson);  
        },  
        onCompleted: function () {  
          options.onCompleted && options.onCompleted();  
        }  
      });  
    },  
    function (error) {  
      options.onFailed && options.onFailed(error);  
      console.log(JSON.stringify(error));  
    }  
  );  
}  
HttpUtils.prototype.upLoadFile = function (options) {  
  var wt = plus.nativeUI.showWaiting();  
  options = options || {};  
  var responseJson = null;  
  var postParams = options.postParams;  
  var postFilesMap = options.postFilesMap;  

  ApiConfig.staticIsDebug('upLoadFile', options.url);  
  var task = plus.uploader.createUpload(options.url, {  
    method: "POST",  
    priority: 100  
  }, function (t, status) {  
    if (status == 200) {  
      try {  
        wt.close();  
        responseJson = JSON.parse(t.responseText);  
        if (responseJson.rt) {  
          ApiConfig.staticIsDebug('responseJson', responseJson, 1);  
          options.onSuccess && options.onSuccess(responseJson);  
        } else {  
          ApiConfig.staticIsDebug('errorJson', responseJson, 1);  
          options.onFailed && options.onFailed(responseJson);  
        }  
      } catch (e) {  
        wt.close();  
        ApiConfig.staticIsDebug('error', e);  
        ApiConfig.staticIsDebug('errorJson', xhr.responseText);  
        options.onFailed && options.onFailed(responseJson);  
      }  
    } else {  
      wt.close();  
      ApiConfig.staticIsDebug('errorJson', responseJson, 1);  
      options.onFailed && options.onFailed(responseJson);  
    }  
  });  
  //task.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
  var keys = postFilesMap.keys();  
  task.addFile(postFilesMap.get(keys[0]), {  
    key: keys[0]  
  });  
  if (postParams) {  
    var paramsKeys = postParams.keys();  
    if (paramsKeys.length > 1) {  
      paramsKeys.forEach(function (key) {  
        task.addData(key, postParams.get(key));  
      })  
    } else {  
      task.addData(paramsKeys[0], postParams.get(paramsKeys[0]));  
    }  
  }  
  task.start();  
}
收起阅读 »

总结下dcloud中遇到的问题

微信登录

1、微信分享返回 code:-100,innerCode:-6解决方案
解决办法: 确认申请时填写的应用签名是否小写,是否去除冒号,签名正确,以上验证过了,确保打包验证,不要debug方式验证
2、code: -2,message: 用户取消,
解决办法:确认申请时填写的包名和打包时是否一致

继续阅读 »

1、微信分享返回 code:-100,innerCode:-6解决方案
解决办法: 确认申请时填写的应用签名是否小写,是否去除冒号,签名正确,以上验证过了,确保打包验证,不要debug方式验证
2、code: -2,message: 用户取消,
解决办法:确认申请时填写的包名和打包时是否一致

收起阅读 »