HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

安卓Native.js蓝牙连接票据打印机完整代码已测试修改

源码 Native.JS

测试机:佳博PT-280便携打印机
手机:华为低端
功能:扫描周围蓝牙设备加入列表,点击未配对设备,自动配对设备,点击已配对设备,进行打印测试
先上html

<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="UTF-8">  

        <title></title>  

        <script src="js/pr.js"></script>  
    </head>  

    <body>  

        <p><input id="bt1" type="button" value="搜索设备" onclick="searchDevices('a')"></p>  

               </button>  

        </div>  

        <div>  
            未配对蓝牙设备  
            <ul id="list1">  

            </ul>  
        </div>  

        <div>  
            已配对蓝牙设备  

            <ul id="list2">  

            </ul>  
        </div>  

    </body>  

</html>

下面是js文件

//address=""搜索蓝牙//address=设备mac地址,自动配对给出mac地址的设备  
function searchDevices(address) {  
    //注册类  
    var main = plus.android.runtimeMainActivity();  
    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
    var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");  
    var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");  
    var BAdapter = BluetoothAdapter.getDefaultAdapter();  
    console.log("开始搜索设备");  
    var filter = new IntentFilter();  
    var bdevice = new BluetoothDevice();  
    var on = null;  
    var un = null;  
    var vlist1 = document.getElementById('list1'); //注册容器用来显示未配对设备  
    vlist1.innerHTML = ''; //清空容器  
    var vlist2 = document.getElementById('list2'); //注册容器用来显示未配对设备  
    vlist2.innerHTML = ''; //清空容器  
    var button1 = document.getElementById('bt1');  
    button1.disabled=true;  
    button1.value='正在搜索请稍候';  
    BAdapter.startDiscovery(); //开启搜索  
    var receiver;  
    receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {  
        onReceive: function(context, intent) { //实现onReceiver回调函数  
            plus.android.importClass(intent); //通过intent实例引入intent类,方便以后的‘.’操作  
            console.log(intent.getAction()); //获取action  
            if(intent.getAction() == "android.bluetooth.adapter.action.DISCOVERY_FINISHED"){  
                main.unregisterReceiver(receiver);//取消监听  
                button1.disabled=false;  
                button1.value='搜索设备';  
                console.log("搜索结束")  
            }else{  
            BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
            //判断是否配对  
            if (BleDevice.getBondState() == bdevice.BOND_NONE) {  
                console.log("未配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());  
                //参数如果跟取得的mac地址一样就配对  
                if (address == BleDevice.getAddress()) {  
                    if (BleDevice.createBond()) { //配对命令.createBond()  
                        console.log("配对成功");  
                        var li2 = document.createElement('li'); //注册  
                        li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                        li2.setAttribute('onclick', 'print(id)'); //注册click点击列表进行打印  
                        li2.innerText = BleDevice.getName();  
                        vlist2.appendChild(li2);  
                    }  

                } else {  
                    if(BleDevice.getName() != on ){ //判断防止重复添加  
                    var li1 = document.createElement('li'); //注册  
                    li1.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                    li1.setAttribute('onclick', 'searchDevices(id)'); //注册click点击列表进行配对  
                    on = BleDevice.getName();  
                    li1.innerText = on;  
                    vlist1.appendChild(li1);  

                    }  

                }  
            } else {  
                if(BleDevice.getName() != un ){ //判断防止重复添加  
                console.log("已配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());  
                var li2 = document.createElement('li'); //注册  
                li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                li2.setAttribute('onclick', 'print(id)'); //注册click点击列表进行打印  
                un = BleDevice.getName();                 
                li2.innerText = un;  
                vlist2.appendChild(li2);}  
            }}  

        }  
    });  

    filter.addAction(bdevice.ACTION_FOUND);  
    filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);  
    filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);  
    filter.addAction(BAdapter.ACTION_STATE_CHANGED);  

    main.registerReceiver(receiver, filter); //注册监听  
}  

var device = null,  
    BAdapter = null,  
    BluetoothAdapter = null,  
    uuid = null,  
    main = null,  
    bluetoothSocket = null;  

function print(mac_address) {  
    if (!mac_address) {  
        mui.toast('请选择蓝牙打印机');  
        return;  
    }  

    main = plus.android.runtimeMainActivity();  
    BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");  
    UUID = plus.android.importClass("java.util.UUID");  
    uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");  
    BAdapter = BluetoothAdapter.getDefaultAdapter();  
    device = BAdapter.getRemoteDevice(mac_address);  
    plus.android.importClass(device);  
    bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);  
    plus.android.importClass(bluetoothSocket);  

    if (!bluetoothSocket.isConnected()) {  
        console.log('检测到设备未连接,尝试连接....');  
        bluetoothSocket.connect();  
    }  

    console.log('设备已连接');  

    if (bluetoothSocket.isConnected()) {  
        var outputStream = bluetoothSocket.getOutputStream();  
        plus.android.importClass(outputStream);  
        var string = "打印测试\r\n";  
        var bytes = plus.android.invoke(string, 'getBytes', 'gbk');  
        outputStream.write(bytes);  
        outputStream.flush();  
        device = null //这里关键  
        bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误  

    }  

}
继续阅读 »

测试机:佳博PT-280便携打印机
手机:华为低端
功能:扫描周围蓝牙设备加入列表,点击未配对设备,自动配对设备,点击已配对设备,进行打印测试
先上html

<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="UTF-8">  

        <title></title>  

        <script src="js/pr.js"></script>  
    </head>  

    <body>  

        <p><input id="bt1" type="button" value="搜索设备" onclick="searchDevices('a')"></p>  

               </button>  

        </div>  

        <div>  
            未配对蓝牙设备  
            <ul id="list1">  

            </ul>  
        </div>  

        <div>  
            已配对蓝牙设备  

            <ul id="list2">  

            </ul>  
        </div>  

    </body>  

</html>

下面是js文件

//address=""搜索蓝牙//address=设备mac地址,自动配对给出mac地址的设备  
function searchDevices(address) {  
    //注册类  
    var main = plus.android.runtimeMainActivity();  
    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
    var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");  
    var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");  
    var BAdapter = BluetoothAdapter.getDefaultAdapter();  
    console.log("开始搜索设备");  
    var filter = new IntentFilter();  
    var bdevice = new BluetoothDevice();  
    var on = null;  
    var un = null;  
    var vlist1 = document.getElementById('list1'); //注册容器用来显示未配对设备  
    vlist1.innerHTML = ''; //清空容器  
    var vlist2 = document.getElementById('list2'); //注册容器用来显示未配对设备  
    vlist2.innerHTML = ''; //清空容器  
    var button1 = document.getElementById('bt1');  
    button1.disabled=true;  
    button1.value='正在搜索请稍候';  
    BAdapter.startDiscovery(); //开启搜索  
    var receiver;  
    receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {  
        onReceive: function(context, intent) { //实现onReceiver回调函数  
            plus.android.importClass(intent); //通过intent实例引入intent类,方便以后的‘.’操作  
            console.log(intent.getAction()); //获取action  
            if(intent.getAction() == "android.bluetooth.adapter.action.DISCOVERY_FINISHED"){  
                main.unregisterReceiver(receiver);//取消监听  
                button1.disabled=false;  
                button1.value='搜索设备';  
                console.log("搜索结束")  
            }else{  
            BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
            //判断是否配对  
            if (BleDevice.getBondState() == bdevice.BOND_NONE) {  
                console.log("未配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());  
                //参数如果跟取得的mac地址一样就配对  
                if (address == BleDevice.getAddress()) {  
                    if (BleDevice.createBond()) { //配对命令.createBond()  
                        console.log("配对成功");  
                        var li2 = document.createElement('li'); //注册  
                        li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                        li2.setAttribute('onclick', 'print(id)'); //注册click点击列表进行打印  
                        li2.innerText = BleDevice.getName();  
                        vlist2.appendChild(li2);  
                    }  

                } else {  
                    if(BleDevice.getName() != on ){ //判断防止重复添加  
                    var li1 = document.createElement('li'); //注册  
                    li1.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                    li1.setAttribute('onclick', 'searchDevices(id)'); //注册click点击列表进行配对  
                    on = BleDevice.getName();  
                    li1.innerText = on;  
                    vlist1.appendChild(li1);  

                    }  

                }  
            } else {  
                if(BleDevice.getName() != un ){ //判断防止重复添加  
                console.log("已配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());  
                var li2 = document.createElement('li'); //注册  
                li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
                li2.setAttribute('onclick', 'print(id)'); //注册click点击列表进行打印  
                un = BleDevice.getName();                 
                li2.innerText = un;  
                vlist2.appendChild(li2);}  
            }}  

        }  
    });  

    filter.addAction(bdevice.ACTION_FOUND);  
    filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);  
    filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);  
    filter.addAction(BAdapter.ACTION_STATE_CHANGED);  

    main.registerReceiver(receiver, filter); //注册监听  
}  

var device = null,  
    BAdapter = null,  
    BluetoothAdapter = null,  
    uuid = null,  
    main = null,  
    bluetoothSocket = null;  

function print(mac_address) {  
    if (!mac_address) {  
        mui.toast('请选择蓝牙打印机');  
        return;  
    }  

    main = plus.android.runtimeMainActivity();  
    BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");  
    UUID = plus.android.importClass("java.util.UUID");  
    uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");  
    BAdapter = BluetoothAdapter.getDefaultAdapter();  
    device = BAdapter.getRemoteDevice(mac_address);  
    plus.android.importClass(device);  
    bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);  
    plus.android.importClass(bluetoothSocket);  

    if (!bluetoothSocket.isConnected()) {  
        console.log('检测到设备未连接,尝试连接....');  
        bluetoothSocket.connect();  
    }  

    console.log('设备已连接');  

    if (bluetoothSocket.isConnected()) {  
        var outputStream = bluetoothSocket.getOutputStream();  
        plus.android.importClass(outputStream);  
        var string = "打印测试\r\n";  
        var bytes = plus.android.invoke(string, 'getBytes', 'gbk');  
        outputStream.write(bytes);  
        outputStream.flush();  
        device = null //这里关键  
        bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误  

    }  

}
收起阅读 »

push进程在小米红米机型下, 应用退出后没有保留

小米, 红米 note2 收不到离线消息

而htc可以收到离线消息

经过测试分析, 怀疑 收不到离线消息的机器在应用退出后 push 和 notify 服务没有保留

还请官方测试一下

小米, 红米 note2 收不到离线消息

而htc可以收到离线消息

经过测试分析, 怀疑 收不到离线消息的机器在应用退出后 push 和 notify 服务没有保留

还请官方测试一下

关于微信分享的实践与问题汇总,比较适合小白~

HTML5+ 分享 分享链接

需求是要向微信朋友圈或者微信好友发送带【缩略图】【标题】【介绍性文字】【链接】的分享,也就是H5+的demo里面share.html里的链接分享

其实我自己也是第一次做这种需求,第一次不知道什么原因,分享出去的总是只有介绍性文字,而没有链接跟缩略图。后来经过请教官方群里的朋友以及自己的琢磨,成功实现了该需求,而且是运用非常小白的方式,下面做一个简单的总结:

1、把官方H5+的demo里的share.html直接copy到自己项目文件中,把对应引入文件的路径修改正确。

2、如果不想或者不会删减share.html里面跟【链接分享】无关的代码,就直接把原有的HTML代码display:none就可以了,这样,部分js不会因为找不到对应的DOM元素而报错(当然这个方法不推荐,只是给新手做参考),比如

        <div id="dcontent" class="dcontent" style="display: none;">

3、接下来就是在share.html页面内部的js中找到shareAction(sb, bh)函数,把控制【缩略图】【标题】【介绍性文字】【链接】的地方赋值为我们自己的内容即可。(在下面的代码的被**包起来的那几行)

            function shareAction(sb, bh) {  
                outSet("分享操作:");  
                if (!sb || !sb.s) {  
                    outLine("无效的分享服务!");  
                    return;  
                }  
                var msg = {  
                    **content: sharecontent.value**,  
                    extra: {  
                        scene: sb.x  
                    }  
                };  
                if (bh) {  
                    **msg.href = sharehref.value;**  
                    if (sharehrefTitle && sharehrefTitle.value != "") {  
                        msg.title = sharehrefTitle.value;  
                    }  
                    if (sharehrefDes && sharehrefDes.value != "") {  
                        msg.content = sharehrefDes.value;  
                    }  
//                  msg.thumbs = ["_www/logo.png"];  
                    **msg.thumbs = [document.getElementById('pic').src];**  
//                  _www/logo.png  
                    msg.pictures = ["_www/logo.png"];  
                } else {  
                    if (pic && pic.realUrl) {  
                        msg.pictures = [pic.realUrl];  
                    }  
                }  
                // 发送分享  
                if (sb.s.authenticated) {  
                    outLine("---已授权---");  
                    shareMessage(msg, sb.s);  
                } else {  
                    outLine("---未授权---");  
                    sb.s.authorize(function() {  
                        shareMessage(msg, sb.s);  
                    }, function(e) {  
                        outLine("认证授权失败:" + e.code + " - " + e.message);  
                    });  
                }  
            }

4、下面是我给以上函数赋值自己新的内容的代码。

mui("#spread-cont").on("tap","li",function(){  
                        var Href=document.getElementById('sharehref');  
                        var Title=document.getElementById('sharehrefTitle');  
                        var Des=document.getElementById('sharehrefDes');  
                        var shareCont=document.getElementById('sharecontent');  
                        var sharePic=document.getElementById('pic');  

                        Href.value=data[this.getAttribute("data-id")].Url;  
                        Title.value=data[this.getAttribute("data-id")].RwName;  
                        Des.value=data[this.getAttribute("data-id")].Content;  
                        shareCont.value=data[this.getAttribute("data-id")].Content;  
                        sharePic.src=data[this.getAttribute("data-id")].Rwtp;  
                        shareHref();  
                    });

5、里面的data[this.getAttribute("data-id")],是我通过ajax获取到的json数据,在该json数据里取出来我自己的【缩略图】【标题】【介绍性文字】【链接】,并进行赋值操作。

6、哈哈,上面的方法非常小白,好怕被大神看到啊~

继续阅读 »

需求是要向微信朋友圈或者微信好友发送带【缩略图】【标题】【介绍性文字】【链接】的分享,也就是H5+的demo里面share.html里的链接分享

其实我自己也是第一次做这种需求,第一次不知道什么原因,分享出去的总是只有介绍性文字,而没有链接跟缩略图。后来经过请教官方群里的朋友以及自己的琢磨,成功实现了该需求,而且是运用非常小白的方式,下面做一个简单的总结:

1、把官方H5+的demo里的share.html直接copy到自己项目文件中,把对应引入文件的路径修改正确。

2、如果不想或者不会删减share.html里面跟【链接分享】无关的代码,就直接把原有的HTML代码display:none就可以了,这样,部分js不会因为找不到对应的DOM元素而报错(当然这个方法不推荐,只是给新手做参考),比如

        <div id="dcontent" class="dcontent" style="display: none;">

3、接下来就是在share.html页面内部的js中找到shareAction(sb, bh)函数,把控制【缩略图】【标题】【介绍性文字】【链接】的地方赋值为我们自己的内容即可。(在下面的代码的被**包起来的那几行)

            function shareAction(sb, bh) {  
                outSet("分享操作:");  
                if (!sb || !sb.s) {  
                    outLine("无效的分享服务!");  
                    return;  
                }  
                var msg = {  
                    **content: sharecontent.value**,  
                    extra: {  
                        scene: sb.x  
                    }  
                };  
                if (bh) {  
                    **msg.href = sharehref.value;**  
                    if (sharehrefTitle && sharehrefTitle.value != "") {  
                        msg.title = sharehrefTitle.value;  
                    }  
                    if (sharehrefDes && sharehrefDes.value != "") {  
                        msg.content = sharehrefDes.value;  
                    }  
//                  msg.thumbs = ["_www/logo.png"];  
                    **msg.thumbs = [document.getElementById('pic').src];**  
//                  _www/logo.png  
                    msg.pictures = ["_www/logo.png"];  
                } else {  
                    if (pic && pic.realUrl) {  
                        msg.pictures = [pic.realUrl];  
                    }  
                }  
                // 发送分享  
                if (sb.s.authenticated) {  
                    outLine("---已授权---");  
                    shareMessage(msg, sb.s);  
                } else {  
                    outLine("---未授权---");  
                    sb.s.authorize(function() {  
                        shareMessage(msg, sb.s);  
                    }, function(e) {  
                        outLine("认证授权失败:" + e.code + " - " + e.message);  
                    });  
                }  
            }

4、下面是我给以上函数赋值自己新的内容的代码。

mui("#spread-cont").on("tap","li",function(){  
                        var Href=document.getElementById('sharehref');  
                        var Title=document.getElementById('sharehrefTitle');  
                        var Des=document.getElementById('sharehrefDes');  
                        var shareCont=document.getElementById('sharecontent');  
                        var sharePic=document.getElementById('pic');  

                        Href.value=data[this.getAttribute("data-id")].Url;  
                        Title.value=data[this.getAttribute("data-id")].RwName;  
                        Des.value=data[this.getAttribute("data-id")].Content;  
                        shareCont.value=data[this.getAttribute("data-id")].Content;  
                        sharePic.src=data[this.getAttribute("data-id")].Rwtp;  
                        shareHref();  
                    });

5、里面的data[this.getAttribute("data-id")],是我通过ajax获取到的json数据,在该json数据里取出来我自己的【缩略图】【标题】【介绍性文字】【链接】,并进行赋值操作。

6、哈哈,上面的方法非常小白,好怕被大神看到啊~

收起阅读 »

给DCloud产品的个人建议

背景:我懂原生 懂Html,Css,Js 三周前了解到了Hbuilder
我的需求 像支付宝一样的开发(原生+ html5) 支付宝APP中有不少应用如:彩票功能,外卖,滴滴等 尤其是那个外卖 就是一个单独的webapp
我也想在自己原生APP中嵌入各个完全不同的webapp,能点击原生控件进入webapp

因为此需求 我好好了解了下Hbuilder 确实有些模糊 花了两个周我加了所有和Builder的群 去每个群里下载了所有的demo 研究后才看懂整个开发流程

因此 有些建议想说说:

1 网站顶部导航增加新手教程 如何一步步从无到有地开发 言简意赅地描述 哪种情景能做什么事情?
2 网站问答感觉可以再细分问题 找相似疑问都不好找哦 感觉论坛更适合开发者 论坛分类整理和搜集有demo的帖子
3 整个DC的产品我觉得可以分为三类 一类是:纯Html5 也就是Runtime环境开发 一类是:原生+webapp开发(也就是widget开发) 一类是:webview开发 应该明确告知新手以便引导学习方向 学习是有时间成本的
4 网站应该将新手分为几类人群 新手也是有类型可分的 比如我:我懂原生开发 有2年工作经验 但是为什么我也是新手呢 因为我才了解Hbuilder开发 不懂这个东西 就得学习 网站应该将新手分为掌握的技能类型 比如:仅懂原生的新手 、 懂原生且懂Html5 css js的新手 、仅懂Html5 css js的新手 、啥都不懂的新手 这四类 分别引导进入不同教程
5 Dc产品未覆盖我的需求这样的效果 建议增加 比如 我想实现的效果是 跟支付宝打开 “外卖” 这个功能按钮的图标后 是从原生webview打开的 打开后是一个webapp应用 DC产品未实现这样的方式 DC产品应该是打开后还有引导页 且 进度条是一个加载项 但我想给客户的感觉就像网页一样打开 也就是想实现的是 原生webview打开widget这个webapp的效果 有进度条 就算不通过webview打开 按照DC产品的widget打开也可否增加一个类似这样效果的 没有引导页的 效果 综上所述 也就是没有在原生APP中像支付宝这样过渡到webapp的效果 是否应该增加一个混合开发模式 现在大部分都是混合开发的
6 新手可能会问 怎么在plus中增加mui框架 怎么在mui框架中调用plus 官方应该给予这个问题明确答案 我想新手都可能会问这个问题 因为Hbuilder中的两个demo感觉就像独立的 怎么整合到一块

感觉DC产品挺好的 这就是我使用过程中的疑问 我相信会有不少新手跟我一样有此疑问和建议

继续阅读 »

背景:我懂原生 懂Html,Css,Js 三周前了解到了Hbuilder
我的需求 像支付宝一样的开发(原生+ html5) 支付宝APP中有不少应用如:彩票功能,外卖,滴滴等 尤其是那个外卖 就是一个单独的webapp
我也想在自己原生APP中嵌入各个完全不同的webapp,能点击原生控件进入webapp

因为此需求 我好好了解了下Hbuilder 确实有些模糊 花了两个周我加了所有和Builder的群 去每个群里下载了所有的demo 研究后才看懂整个开发流程

因此 有些建议想说说:

1 网站顶部导航增加新手教程 如何一步步从无到有地开发 言简意赅地描述 哪种情景能做什么事情?
2 网站问答感觉可以再细分问题 找相似疑问都不好找哦 感觉论坛更适合开发者 论坛分类整理和搜集有demo的帖子
3 整个DC的产品我觉得可以分为三类 一类是:纯Html5 也就是Runtime环境开发 一类是:原生+webapp开发(也就是widget开发) 一类是:webview开发 应该明确告知新手以便引导学习方向 学习是有时间成本的
4 网站应该将新手分为几类人群 新手也是有类型可分的 比如我:我懂原生开发 有2年工作经验 但是为什么我也是新手呢 因为我才了解Hbuilder开发 不懂这个东西 就得学习 网站应该将新手分为掌握的技能类型 比如:仅懂原生的新手 、 懂原生且懂Html5 css js的新手 、仅懂Html5 css js的新手 、啥都不懂的新手 这四类 分别引导进入不同教程
5 Dc产品未覆盖我的需求这样的效果 建议增加 比如 我想实现的效果是 跟支付宝打开 “外卖” 这个功能按钮的图标后 是从原生webview打开的 打开后是一个webapp应用 DC产品未实现这样的方式 DC产品应该是打开后还有引导页 且 进度条是一个加载项 但我想给客户的感觉就像网页一样打开 也就是想实现的是 原生webview打开widget这个webapp的效果 有进度条 就算不通过webview打开 按照DC产品的widget打开也可否增加一个类似这样效果的 没有引导页的 效果 综上所述 也就是没有在原生APP中像支付宝这样过渡到webapp的效果 是否应该增加一个混合开发模式 现在大部分都是混合开发的
6 新手可能会问 怎么在plus中增加mui框架 怎么在mui框架中调用plus 官方应该给予这个问题明确答案 我想新手都可能会问这个问题 因为Hbuilder中的两个demo感觉就像独立的 怎么整合到一块

感觉DC产品挺好的 这就是我使用过程中的疑问 我相信会有不少新手跟我一样有此疑问和建议

收起阅读 »

mui 能不能内置一个图片相册浏览功能?

mui

类似微信这样的, 这个功能应该挺普遍的吧。

类似微信这样的, 这个功能应该挺普遍的吧。

判断网络是否连接

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />  
    <title>hello world</title>  
    <script type="text/javascript" src="js/mui.min.js"></script>  
</head>  
<body>  
<script type="text/javascript" charset="utf-8">  
mui.plusReady(function() {  
    document.addEventListener("netchange", wainshow, false);  
});  

function wainshow() {  
    if (plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_NONE) {  
        mui.toast("网络异常,请检查网络设置!");  

    } else {  
        mui.toast("网络正常");  
    }  
}  
</script>  
<div onclick="wainshow();">111111</div>  
</body>  
</html>
继续阅读 »
<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />  
    <title>hello world</title>  
    <script type="text/javascript" src="js/mui.min.js"></script>  
</head>  
<body>  
<script type="text/javascript" charset="utf-8">  
mui.plusReady(function() {  
    document.addEventListener("netchange", wainshow, false);  
});  

function wainshow() {  
    if (plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_NONE) {  
        mui.toast("网络异常,请检查网络设置!");  

    } else {  
        mui.toast("网络正常");  
    }  
}  
</script>  
<div onclick="wainshow();">111111</div>  
</body>  
</html>
收起阅读 »

分享个人写的用于项目的全选和取消以及全选按钮随着子类选项的状态变化而变化

<div class="mui-content">  

                <form class="mui-input-group">  
                    <div class="mui-input-row mui-checkbox">  
                        <label>全部</label>  
                        <input id="selectall"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级一班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级二班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级三班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                </form>  
            </div>
<script type="text/javascript">  
        var chkall=document.getElementById("selectall");  
        mui.plusReady(function(){  
            chkall.addEventListener("change",function(){  
                if(this.checked){  
                    mui("input[name='subcheck']").each(function(){  
                        this.checked=true;  

                    });  
                }else{  
                    mui("input[name='subcheck']").each(function(){  
                        this.checked=false;  

                    });  
                }  
            },false);  

            var cbknum=mui("input[name='subcheck']").length;  
             var chknum=0;      
            mui(".mui-input-group").on("change","input[name='subcheck']",function(){  

                if(this.checked)  
                {  
                    chknum++;  

                }else{  
                    chknum--;  
                }  
                if(cbknum==chknum){  

                    chkall.checked=true;  
                }else{  
                    chkall.checked=false;  

                }  

            });  

        });  
继续阅读 »
<div class="mui-content">  

                <form class="mui-input-group">  
                    <div class="mui-input-row mui-checkbox">  
                        <label>全部</label>  
                        <input id="selectall"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级一班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级二班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                    <div class="mui-input-row mui-checkbox">  
                        <label>四年级三班</label>  
                        <input name="subcheck"  type="checkbox">  
                    </div>  
                </form>  
            </div>
<script type="text/javascript">  
        var chkall=document.getElementById("selectall");  
        mui.plusReady(function(){  
            chkall.addEventListener("change",function(){  
                if(this.checked){  
                    mui("input[name='subcheck']").each(function(){  
                        this.checked=true;  

                    });  
                }else{  
                    mui("input[name='subcheck']").each(function(){  
                        this.checked=false;  

                    });  
                }  
            },false);  

            var cbknum=mui("input[name='subcheck']").length;  
             var chknum=0;      
            mui(".mui-input-group").on("change","input[name='subcheck']",function(){  

                if(this.checked)  
                {  
                    chknum++;  

                }else{  
                    chknum--;  
                }  
                if(cbknum==chknum){  

                    chkall.checked=true;  
                }else{  
                    chkall.checked=false;  

                }  

            });  

        });  
收起阅读 »

使用纯HTML5编写一款网页上的时钟的代码分享

你需要知道的:
canvas标签只是图形容器,您必须使用脚本来绘制图形。默认大小:宽300px,高150px;
getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。——获取上下文对象。
getContext("2d") 对象属性和方法,可用于在画布上绘制文本、线条、矩形、圆形等等。
fillRect(l,t,w,h):默认颜色是黑色 strokeRect(l,t,w,h):带边框的方块。默认一像素黑色边框
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
beginPath():定义开始绘制路径, 它把当前的点设置为 (0,0)。 当一个画布的环境第一次创建,beginPath()
方法会被显式地调用。
closePath():结束绘制路径(将起点与终点进行连接)

绘制圆形:
arc( x,y,半径,起始弧度,结束弧度,旋转方向)
x,y:起始位置
弧度与角度的关系:弧度=角度*Math.PI/180
旋转方向:顺时针(默认:false,逆时针:true)
代码:
XML/HTML Code复制内容到剪贴板
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script>
window.onload = function(){
var oC = document.getElementById('ch1');
var oGC = oC.getContext('2d');

                    function drawClock(){     
                            var x = 200;   //指定坐标     
                            var y = 200;     
                            var r = 150;  //指定钟表半径     

                            oGC.clearRect(0,0,oC.width,oC.height);//清空画布     

                            var oDate = new Date();      //创建日期对象     
                            var oHours = oDate.getHours();//获取时间     
                            var oMin = oDate.getMinutes();     
                            var oSen = oDate.getSeconds();     

                            var oHoursValue = (-90 + oHours*30 + oMin/2)*Math.PI/180; //设置时针的值     
                            var oMinValue = (-90 + oMin*6)*Math.PI/180;     
                            var oSenValue = (-90 + oSen*6)*Math.PI/180;     

                            oGC.beginPath();//开始     

                            for(var i=0;i<60;i++){         //i为60,代表着时钟的60个小刻度     
                                    oGC.moveTo(x,y);     
                                    oGC.arc(x,y,r,6*i*Math.PI/180,6*(i+1)*Math.PI/180,false); //循环从6度到12度     
                            }     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.fillStyle ='white'; //覆盖住小刻度的黑色线     
                            oGC.beginPath();     
                            oGC.moveTo(x,y);     
                            oGC.arc(x,y,r*19/20,0,360*(i+1)*Math.PI/180,false);     

                            oGC.closePath();//结束     
                            oGC.fill();     

                            oGC.lineWidth = 3; //设置时钟圆盘大刻度的粗细值     
                            oGC.beginPath();  //开始画大的时钟刻度     

                            for(i=0;i<12;i++){              //i为12,代表着时钟刻度的12大格     
                                    oGC.moveTo(x,y);     
                                    oGC.arc(x,y,r,30*i*Math.PI/180,30*(i+1)*Math.PI/180,false); // 间隔为30度,弧度=角度*Math.PI/180     
                            }     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.fillStyle ='white'; //覆盖住大刻度的黑色线     
                            oGC.beginPath();     
                            oGC.moveTo(x,y);     
                            oGC.arc(x,y,r*18/20,360*(i+1)*Math.PI/180,false);     

                            oGC.closePath();     
                            oGC.fill();//表盘完成      

                            oGC.lineWidth = 5;//设置时针宽度     
                            oGC.beginPath();//开始绘制时针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*10/20,oHoursValue,oHoursValue,false);//设置时针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.lineWidth = 3;//设置分针宽度     
                            oGC.beginPath();//开始绘制分针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*14/20,oMinValue,oMinValue,false);//设置分针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.lineWidth = 1;//设置秒针宽度     
                            oGC.beginPath();//开始绘制秒针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*19/20,oSenValue,oSenValue,false);//设置秒针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     
                    }     
                    setInterval(drawClock,1000);//设置定时器,让时钟运转起来     
                            drawClock();     
            };     
    </script>    

</head>
<body>
<canvas id = "ch1" width = "400px" height = "400px"></canvas>
</body>
</html>
点击下方result查看演示:www.szyoudun.com

继续阅读 »

你需要知道的:
canvas标签只是图形容器,您必须使用脚本来绘制图形。默认大小:宽300px,高150px;
getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。——获取上下文对象。
getContext("2d") 对象属性和方法,可用于在画布上绘制文本、线条、矩形、圆形等等。
fillRect(l,t,w,h):默认颜色是黑色 strokeRect(l,t,w,h):带边框的方块。默认一像素黑色边框
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
beginPath():定义开始绘制路径, 它把当前的点设置为 (0,0)。 当一个画布的环境第一次创建,beginPath()
方法会被显式地调用。
closePath():结束绘制路径(将起点与终点进行连接)

绘制圆形:
arc( x,y,半径,起始弧度,结束弧度,旋转方向)
x,y:起始位置
弧度与角度的关系:弧度=角度*Math.PI/180
旋转方向:顺时针(默认:false,逆时针:true)
代码:
XML/HTML Code复制内容到剪贴板
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script>
window.onload = function(){
var oC = document.getElementById('ch1');
var oGC = oC.getContext('2d');

                    function drawClock(){     
                            var x = 200;   //指定坐标     
                            var y = 200;     
                            var r = 150;  //指定钟表半径     

                            oGC.clearRect(0,0,oC.width,oC.height);//清空画布     

                            var oDate = new Date();      //创建日期对象     
                            var oHours = oDate.getHours();//获取时间     
                            var oMin = oDate.getMinutes();     
                            var oSen = oDate.getSeconds();     

                            var oHoursValue = (-90 + oHours*30 + oMin/2)*Math.PI/180; //设置时针的值     
                            var oMinValue = (-90 + oMin*6)*Math.PI/180;     
                            var oSenValue = (-90 + oSen*6)*Math.PI/180;     

                            oGC.beginPath();//开始     

                            for(var i=0;i<60;i++){         //i为60,代表着时钟的60个小刻度     
                                    oGC.moveTo(x,y);     
                                    oGC.arc(x,y,r,6*i*Math.PI/180,6*(i+1)*Math.PI/180,false); //循环从6度到12度     
                            }     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.fillStyle ='white'; //覆盖住小刻度的黑色线     
                            oGC.beginPath();     
                            oGC.moveTo(x,y);     
                            oGC.arc(x,y,r*19/20,0,360*(i+1)*Math.PI/180,false);     

                            oGC.closePath();//结束     
                            oGC.fill();     

                            oGC.lineWidth = 3; //设置时钟圆盘大刻度的粗细值     
                            oGC.beginPath();  //开始画大的时钟刻度     

                            for(i=0;i<12;i++){              //i为12,代表着时钟刻度的12大格     
                                    oGC.moveTo(x,y);     
                                    oGC.arc(x,y,r,30*i*Math.PI/180,30*(i+1)*Math.PI/180,false); // 间隔为30度,弧度=角度*Math.PI/180     
                            }     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.fillStyle ='white'; //覆盖住大刻度的黑色线     
                            oGC.beginPath();     
                            oGC.moveTo(x,y);     
                            oGC.arc(x,y,r*18/20,360*(i+1)*Math.PI/180,false);     

                            oGC.closePath();     
                            oGC.fill();//表盘完成      

                            oGC.lineWidth = 5;//设置时针宽度     
                            oGC.beginPath();//开始绘制时针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*10/20,oHoursValue,oHoursValue,false);//设置时针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.lineWidth = 3;//设置分针宽度     
                            oGC.beginPath();//开始绘制分针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*14/20,oMinValue,oMinValue,false);//设置分针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     

                            oGC.lineWidth = 1;//设置秒针宽度     
                            oGC.beginPath();//开始绘制秒针     
                            oGC.moveTo(x,y);     

                            oGC.arc(x,y,r*19/20,oSenValue,oSenValue,false);//设置秒针大小和弧度     
                            oGC.closePath();     
                            oGC.stroke();     
                    }     
                    setInterval(drawClock,1000);//设置定时器,让时钟运转起来     
                            drawClock();     
            };     
    </script>    

</head>
<body>
<canvas id = "ch1" width = "400px" height = "400px"></canvas>
</body>
</html>
点击下方result查看演示:www.szyoudun.com

收起阅读 »

用HTML5.0制作网页的教程

根据你们询问的人,HTML 5不是迈向创造更语义化的网络的下一 个重要步伐,就是用一系列不完整的标签和标记大杂烩让网络陷入困境的灾难。
争论双方的问题在于,很少的站点在自然环境下使用HTML 5,所以现在所认识到的问题的理论解决方案仍然在很大程度上未经考验。
即便如此,我们不难发现下一代网络标记工具的好处和潜在的问题。
内容

  1. HTML 5有什么不同?
  2. 最终,一个任何人都可以记住的文档类型
  3. 最基本的语义结构
  4. <header>
  5. <nav>
  6. <section>
  7. <article>
  8. <aside>
  9. <footer>
  10. 把他们放在一起
  11. 为新元素编写样式
  12. 兼容老的浏览器
  13. 现在你可以使用HTML 5了,但你会用么?
    HTML 5有什么不同?
    首先,我们通过HTML 5表达什么?First off, what do we mean by HTML 5?理论上,我们表达所有的事——新的语义结构标签,例如canvas或者离线储存等API规范,以及新的内联语义标签。尽管如此,我们把实际的原因 (PS:浏览器支持问题)仅仅局限于结构标签。canvas,离线储存,本地视频或者地理定位API都很绝妙,然而他们还不能被所有浏览器一致的支持。
    “但是等等”你说,“大多数浏览器也都不支持新的结构元素!”这是真的,但他们中的绝大多数将 会很乐意去接受你想要创建的任何标签。甚至连IE6也可以处理新标签,尽管如果你想要使用CSS设置样式,你需要一点JavaScript的帮助。
    当你对新标签设置样式时,你需要记住一件事,那就是未知标签在大部分浏览器中没有默认样式。他 们同时被认为是行级元素。尽管如此,由于大部分HTML 5的新标签可以构造,我们将让他们拥有块级元素的行为。解决方法是确认你在CSS样式中包含了display:block;。
    为了帮助了解当今HTML 5的一些新玩意儿,我们现在就进入正题,开始使用一些新的结构元素。
    最终,一个任何人都可以记住的文档类型
    我们创建HTML 5文档第一件需要做的事情就是使用新的文档类型。现在,如果你还清楚的记得HTML 4或者XHTML 1.x的文档类型,你真是一个比我们更强的淘气鬼。每当我们新建一个页面,我们必须打开一个旧的文件,剪切并粘贴文档类型定义。
    这真是痛苦,也是为什么我们喜欢新的HTML 5文档类型。你准备好了么?他出现了:

不会太难记。简单并且容易理解。不区分大小写。
这个构想是停止HTML版本化,使向后兼容变得更容易。从长远看是否成功是另外的事情,但至少 他节省了你输入的平均时间。
最基本语义结构
我们已经将我们的页面定义为HTML 5文档。到现在为止,一切都还不错。现在,这些我们已经听说的新标签到底是什么?
在我们钻研新标签前,想想你一般网页的结构,大概像这样:

这对于展示用途很好,但如果我们想要知道一些关于页面元素包含什么的问题,这又怎么办呢?
上面的例子中,我们为我们所有的结构div添加了ID。这在有见识的设计师中是很平常的事。目 的有两个方面,首先,ID提供了可以能用于给页面的特殊段落应用样式的锚,其次,ID充当基本的伪语义结构。高明的解析器将会查看标签的ID属性,并尝试 去猜测他们的含义,但当每个站点的ID名称不同的时候很难。
这就是新结构标签到来的理由。
当认识到这些ID成为了惯例,HTML 5的缔造者们更进一步,使这些元素中的一部分变成他们独立的标签。这儿有一个HTML 5中生效的新标签的快速概要:
<header>
头部标签被设计作为关于一个章节或者一整张网页介绍信息的容器。<header> 标签可以包含从你位于大多数页面顶部的典型标志或者标语,到介绍一个章节的标语和开场白的任何东西。如果你还在你的页面里使用<div id=”header”>,那可以使用<header>替换
<nav>
nav元素非常明显,这是你的导航元素。当然什么被算为导航是有一些争议的,有一个基本的站点 导航,但一些情况下还可能有页面导航元素。HTML5的缔造者WHATWG最近在修改<nav>的解释,来表现怎样在同一个页面使用两次。
更多关于nav的信息以及关于HTML5的激烈争论,参见Jeffrey Zeldman关于nav元素的文章。
如果你还在使用<div id=”nav”>标签来包含你的页面导航,你可以使用简洁的<nav>标签来替换。
<section>
Section可能是新标签中最模糊的。根据HTML 5定义,一个章节是一个内容的主题集合,通常在header标签后,在footer标签前。但是如果 需要,section也可以相互嵌套。
在我们上面的例子里,被“content”标记的div就是一个变为section的很好的选 择。另外在那个section内,根据内容,我们可以增加section。
<article>
根绝WHATWG的注释,article元素可以包含“组成文档或站点独立部分的一段内容;例 如,杂志或者新闻的文章,或者博客条目。”
记住一个页面里可以有多个article标签;例如一个博客首页可能有最新的十篇文章,每一篇 包含在一个article标签内。Article也可以通过使用section标签分为多个段落,然而当你计划你的结构时需要稍微仔细一些,否则你容易引 起以一些难看的标签大杂烩结尾的情况。
<aside>
另一个相当模糊的标签,aside元素用于“与组成文档主要的正文流内容无关的”内容。那表示 一条附加的评论,内联的脚注,引用,注解或者像你看到的在这篇文章右边的更多典型的边栏内容。
根据WHATWG的注释,看起来<aside>可以用于所有的这些情况,尽管你边 栏里的引用和标签云有着很大的不同。
没人说HTML 5是完美的!
<footer>
Footer的用处也应该是很明显的,除了可能你不清楚可以拥有多个脚标。换句话说,除了通常 在大多数页面底部看到的主脚标,段落也可以含有脚标。
把他们放在一起
让我们使用新标签重新编写我们原来的例子:

非常清楚,并且容易理解,不是么?一些注释:我们可以在header标签中包含我们 的<h1>My Article</h1>标题。我没有这样做,因为h1元素已经表达了标题的含义,但如果你还有发布日期,署名或者其他数据在你文章的顶部, 为标签集添加一个header容器标签是一个很好的选择。
同时注意我们可以在article元素下添加第二个footer元素来包含诸如翻页导航,相关 文章或者其他内容。
为新标签编写样式
在大多数浏览器中,所有你需要做的就是像你通常做的那样,为在新标签上应用样式表,简单的定义 你的样式。但请确认为每一个元素添加了display:block;规则,无论如何,从现在开始。经过一段时间后,当浏览器开始标准化,并支持新元素后, 那就不必要了。
例如,让我们在我们的header里应用一些样式:

记住,你仍然可以给这些标签添加类和ID属性。所以,如果你想要单独为一个导航设置样式,你可 以轻易的给这个标签添加一个类或者样式,就象这样:

然后你可以应用一个样式:

兼容老的浏览器
但等一下,IE怎么办?这些样式完全不能在IE6下工作。如果你仍然需要支持像IE6一类遗产 般的浏览器,这儿有一个解决方法。IE6解析和显示这些标签还好,但你不能对他们设置任何CSS。解决方法是使用一点JavaScript。
我们只需要让IE去给我们使用createElement方法创造的的HTML 5标签设置样式。在HTML 5文件的head标签内添加这点东西。或者,你可以把他保存在一个特定的文件里,并用这种方法包含。

我知道你在想什么:“哥,你根本没有为那个脚本标签定义一个MIME类型。”
你根本不需要在HTML 5做这些事情。在HTML 5中,所有的脚本都被假定为type=”text/javascript”,所以没有必要让属性把你的脚本标签搞得乱七八糟(除非你的脚本并不是 JavaScript)。
这解决了IE的问题,但我们并没有摆脱困境。现在被证明Gecko渲染引擎有一个bug,导致 了Firefox2和Camino的一些版本在这些标签上卡住。
这儿有两个方法来处理这个bug,没有一个是理想的。更多的细节请查看HTML5doctor的这篇文章。这篇文章同时附有一个让所有HTML 5元素都生效的方便脚本。
记住,尽管Firefox 2的使用率很快在所有网站流量中降到了10%以下,但单纯忽略这个bug可能还是需要根据你网站的访问者来定。
现在你可以使用HTML 5了,但你会用么?
简短的回答是:我们会。
复杂一点的是:那要看站点了。如果你指责重新制作CNN主页,好吧,你可能会有一点抗拒,直到 浏览器的支持变好些。但如果你要给你的博客改版,我们支持你。这儿还有一些可以帮助你的Wordpress插 件,如果你正在使用这么流行的发布系统。这儿是一个Jeff Starr制作的HTML 5主题。
同时,试试以站点为主的HTML 5美术馆,并且查看源代码,看看他们做了什么。
尽管如此,如果IE的缺点阻止你了,这样考虑吧:就连Google也在他们的主要搜索页面上使 用了HTML 5的文档类型。就算如果你不使用所有新的结构标签,你可以至少利用一下简洁的脚本声明和下次我们会介绍的关于一些非结构的语义标签。www.szyoudun.com

继续阅读 »

根据你们询问的人,HTML 5不是迈向创造更语义化的网络的下一 个重要步伐,就是用一系列不完整的标签和标记大杂烩让网络陷入困境的灾难。
争论双方的问题在于,很少的站点在自然环境下使用HTML 5,所以现在所认识到的问题的理论解决方案仍然在很大程度上未经考验。
即便如此,我们不难发现下一代网络标记工具的好处和潜在的问题。
内容

  1. HTML 5有什么不同?
  2. 最终,一个任何人都可以记住的文档类型
  3. 最基本的语义结构
  4. <header>
  5. <nav>
  6. <section>
  7. <article>
  8. <aside>
  9. <footer>
  10. 把他们放在一起
  11. 为新元素编写样式
  12. 兼容老的浏览器
  13. 现在你可以使用HTML 5了,但你会用么?
    HTML 5有什么不同?
    首先,我们通过HTML 5表达什么?First off, what do we mean by HTML 5?理论上,我们表达所有的事——新的语义结构标签,例如canvas或者离线储存等API规范,以及新的内联语义标签。尽管如此,我们把实际的原因 (PS:浏览器支持问题)仅仅局限于结构标签。canvas,离线储存,本地视频或者地理定位API都很绝妙,然而他们还不能被所有浏览器一致的支持。
    “但是等等”你说,“大多数浏览器也都不支持新的结构元素!”这是真的,但他们中的绝大多数将 会很乐意去接受你想要创建的任何标签。甚至连IE6也可以处理新标签,尽管如果你想要使用CSS设置样式,你需要一点JavaScript的帮助。
    当你对新标签设置样式时,你需要记住一件事,那就是未知标签在大部分浏览器中没有默认样式。他 们同时被认为是行级元素。尽管如此,由于大部分HTML 5的新标签可以构造,我们将让他们拥有块级元素的行为。解决方法是确认你在CSS样式中包含了display:block;。
    为了帮助了解当今HTML 5的一些新玩意儿,我们现在就进入正题,开始使用一些新的结构元素。
    最终,一个任何人都可以记住的文档类型
    我们创建HTML 5文档第一件需要做的事情就是使用新的文档类型。现在,如果你还清楚的记得HTML 4或者XHTML 1.x的文档类型,你真是一个比我们更强的淘气鬼。每当我们新建一个页面,我们必须打开一个旧的文件,剪切并粘贴文档类型定义。
    这真是痛苦,也是为什么我们喜欢新的HTML 5文档类型。你准备好了么?他出现了:

不会太难记。简单并且容易理解。不区分大小写。
这个构想是停止HTML版本化,使向后兼容变得更容易。从长远看是否成功是另外的事情,但至少 他节省了你输入的平均时间。
最基本语义结构
我们已经将我们的页面定义为HTML 5文档。到现在为止,一切都还不错。现在,这些我们已经听说的新标签到底是什么?
在我们钻研新标签前,想想你一般网页的结构,大概像这样:

这对于展示用途很好,但如果我们想要知道一些关于页面元素包含什么的问题,这又怎么办呢?
上面的例子中,我们为我们所有的结构div添加了ID。这在有见识的设计师中是很平常的事。目 的有两个方面,首先,ID提供了可以能用于给页面的特殊段落应用样式的锚,其次,ID充当基本的伪语义结构。高明的解析器将会查看标签的ID属性,并尝试 去猜测他们的含义,但当每个站点的ID名称不同的时候很难。
这就是新结构标签到来的理由。
当认识到这些ID成为了惯例,HTML 5的缔造者们更进一步,使这些元素中的一部分变成他们独立的标签。这儿有一个HTML 5中生效的新标签的快速概要:
<header>
头部标签被设计作为关于一个章节或者一整张网页介绍信息的容器。<header> 标签可以包含从你位于大多数页面顶部的典型标志或者标语,到介绍一个章节的标语和开场白的任何东西。如果你还在你的页面里使用<div id=”header”>,那可以使用<header>替换
<nav>
nav元素非常明显,这是你的导航元素。当然什么被算为导航是有一些争议的,有一个基本的站点 导航,但一些情况下还可能有页面导航元素。HTML5的缔造者WHATWG最近在修改<nav>的解释,来表现怎样在同一个页面使用两次。
更多关于nav的信息以及关于HTML5的激烈争论,参见Jeffrey Zeldman关于nav元素的文章。
如果你还在使用<div id=”nav”>标签来包含你的页面导航,你可以使用简洁的<nav>标签来替换。
<section>
Section可能是新标签中最模糊的。根据HTML 5定义,一个章节是一个内容的主题集合,通常在header标签后,在footer标签前。但是如果 需要,section也可以相互嵌套。
在我们上面的例子里,被“content”标记的div就是一个变为section的很好的选 择。另外在那个section内,根据内容,我们可以增加section。
<article>
根绝WHATWG的注释,article元素可以包含“组成文档或站点独立部分的一段内容;例 如,杂志或者新闻的文章,或者博客条目。”
记住一个页面里可以有多个article标签;例如一个博客首页可能有最新的十篇文章,每一篇 包含在一个article标签内。Article也可以通过使用section标签分为多个段落,然而当你计划你的结构时需要稍微仔细一些,否则你容易引 起以一些难看的标签大杂烩结尾的情况。
<aside>
另一个相当模糊的标签,aside元素用于“与组成文档主要的正文流内容无关的”内容。那表示 一条附加的评论,内联的脚注,引用,注解或者像你看到的在这篇文章右边的更多典型的边栏内容。
根据WHATWG的注释,看起来<aside>可以用于所有的这些情况,尽管你边 栏里的引用和标签云有着很大的不同。
没人说HTML 5是完美的!
<footer>
Footer的用处也应该是很明显的,除了可能你不清楚可以拥有多个脚标。换句话说,除了通常 在大多数页面底部看到的主脚标,段落也可以含有脚标。
把他们放在一起
让我们使用新标签重新编写我们原来的例子:

非常清楚,并且容易理解,不是么?一些注释:我们可以在header标签中包含我们 的<h1>My Article</h1>标题。我没有这样做,因为h1元素已经表达了标题的含义,但如果你还有发布日期,署名或者其他数据在你文章的顶部, 为标签集添加一个header容器标签是一个很好的选择。
同时注意我们可以在article元素下添加第二个footer元素来包含诸如翻页导航,相关 文章或者其他内容。
为新标签编写样式
在大多数浏览器中,所有你需要做的就是像你通常做的那样,为在新标签上应用样式表,简单的定义 你的样式。但请确认为每一个元素添加了display:block;规则,无论如何,从现在开始。经过一段时间后,当浏览器开始标准化,并支持新元素后, 那就不必要了。
例如,让我们在我们的header里应用一些样式:

记住,你仍然可以给这些标签添加类和ID属性。所以,如果你想要单独为一个导航设置样式,你可 以轻易的给这个标签添加一个类或者样式,就象这样:

然后你可以应用一个样式:

兼容老的浏览器
但等一下,IE怎么办?这些样式完全不能在IE6下工作。如果你仍然需要支持像IE6一类遗产 般的浏览器,这儿有一个解决方法。IE6解析和显示这些标签还好,但你不能对他们设置任何CSS。解决方法是使用一点JavaScript。
我们只需要让IE去给我们使用createElement方法创造的的HTML 5标签设置样式。在HTML 5文件的head标签内添加这点东西。或者,你可以把他保存在一个特定的文件里,并用这种方法包含。

我知道你在想什么:“哥,你根本没有为那个脚本标签定义一个MIME类型。”
你根本不需要在HTML 5做这些事情。在HTML 5中,所有的脚本都被假定为type=”text/javascript”,所以没有必要让属性把你的脚本标签搞得乱七八糟(除非你的脚本并不是 JavaScript)。
这解决了IE的问题,但我们并没有摆脱困境。现在被证明Gecko渲染引擎有一个bug,导致 了Firefox2和Camino的一些版本在这些标签上卡住。
这儿有两个方法来处理这个bug,没有一个是理想的。更多的细节请查看HTML5doctor的这篇文章。这篇文章同时附有一个让所有HTML 5元素都生效的方便脚本。
记住,尽管Firefox 2的使用率很快在所有网站流量中降到了10%以下,但单纯忽略这个bug可能还是需要根据你网站的访问者来定。
现在你可以使用HTML 5了,但你会用么?
简短的回答是:我们会。
复杂一点的是:那要看站点了。如果你指责重新制作CNN主页,好吧,你可能会有一点抗拒,直到 浏览器的支持变好些。但如果你要给你的博客改版,我们支持你。这儿还有一些可以帮助你的Wordpress插 件,如果你正在使用这么流行的发布系统。这儿是一个Jeff Starr制作的HTML 5主题。
同时,试试以站点为主的HTML 5美术馆,并且查看源代码,看看他们做了什么。
尽管如此,如果IE的缺点阻止你了,这样考虑吧:就连Google也在他们的主要搜索页面上使 用了HTML 5的文档类型。就算如果你不使用所有新的结构标签,你可以至少利用一下简洁的脚本声明和下次我们会介绍的关于一些非结构的语义标签。www.szyoudun.com

收起阅读 »

基于HTML5的云虚拟主机配置界面

云计算大行其道,上期开源中国的原创会就有好几位云计算专家演讲,从底层的虚拟化技术,到上层的云存储和应用API,耳濡目染,也受益匪浅,算是大势所趋,回头看看Qunee组件,借这个趋势,可以在云计算可视化上发挥作用,最近就有客户用Qunee实现VPC配置图,并对交互做了定制,细节不便多说,本文主要介绍Qunee交互扩展方面的思路

云计算大行其道,上期开源中国的原创会就有好几位云计算专家演讲,从底层的虚拟化技术,到上层的云存储和应用API,耳濡目染,也受益匪浅,算是大势所趋,回头看看Qunee组件,借这个趋势,可以在云计算可视化上发挥作用,最近就有客户用Qunee实现VPC配置图,并对交互做了定制,细节不便多说,本文主要介绍Qunee交互扩展方面的思路

VPC配置图

参考示例 – visualops

云平台可视化这块儿国外做的不错,有不少开放的示例可以学习和参考,客户看中了这家云管理系统http://www.visualops.io/ ,这个系统使用的是SVG技术,体验了一下,效果不错,参照着实现

从界面上看,一个云节点上有多个子网,每个子网内有多台虚拟主机,然后每个云节点有统一的路由Router管理(或者网关Gateway)

visualops

界面呈现

参照原型实现,使用Q.Path描出子网和云节点范围,虚拟机则用普通节点,连线使用正交连线类型,此外还有些外观配置,比如虚线,背景颜色,网格等,设置style或者css即可

创建矩形元素(子网、云节点)

function createRect(name, left, top, width, height, fillColor) {
var rect = graph.createNode(name, left, top);
rect.type = "rectGroup";
rect.anchorPosition = Q.Position.LEFT_TOP;
rect.image = Q.Shapes.getRect(0, 0, 100, 100);
rect.size = {width: width, height: height};
rect.setStyle(Q.Styles.IMAGE_BACKGROUND_COLOR, fillColor || Q.toColor(0x88FFFFFF));
rect.setStyle(Q.Styles.SHAPE_STROKE, 0);
rect.setStyle(Q.Styles.BORDER, 1);
rect.setStyle(Q.Styles.BORDER_COLOR, "#32c02f");
rect.setStyle(Q.Styles.BORDER_LINE_DASH, [5, 6]);
rect.setStyle(Q.Styles.LABEL_PADDING, 5);
rect.setStyle(Q.Styles.LABEL_ANCHOR_POSITION, Q.Position.LEFT_TOP);
rect.setStyle(Q.Styles.LABEL_POSITION, Q.Position.LEFT_TOP);
rect.setBounds = function (bounds) {
this.x = bounds.x;
this.y = bounds.y;
this.size = new Q.Size(bounds.width, bounds.height);
}
rect.getBounds = function () {
return new Q.Rect(this.x, this.y, this.size.width, this.size.height);
}
rect.inBounds = function (x, y) {
return this.getBounds().contains(x, y);
}
rect.intersectsRect = function (rect) {
return rect.intersectsRect(this.x, this.y, this.size.width, this.size.height);
}
rect.containsRect = function (rect) {
return Q.containsRect(this.x, this.y, this.size.width, this.size.height, rect.x, rect.y, rect.width, rect.height);
}
rect.updateBoundsByChildren = function () {
var bounds = new Q.Rect();
Q.forEachChild(this, function (child) {
bounds.add(graph.getUIBounds(child));
});
this.location = new Q.Point(bounds.x, bounds.y - 15);
this.size = new Q.Size(Math.max(200, bounds.width), Math.max(70, bounds.height + 15));
}
return rect;
}
注意到对Rect增加了一些标定节点范围、计算自身大小的方法,后面交互时会用到

创建虚拟主机

function createPC(name, x, y, parent) {
var node = graph.createNode(name, x, y);
node.image = Q.Graphs.server;
node.parent = node.host = parent;
node.zIndex = 10;
return node;
}
创建连接关系

function createEdge(from, to) {
var name = from.name + "->" + to.name;
var edge = graph.createEdge(name, from, to);
edge.edgeType = Q.Consts.EDGE_TYPE_VERTICAL_HORIZONTAL;
edge.setStyle(Q.Styles.EDGE_FROM_OFFSET, {x: 20});
edge.setStyle(Q.Styles.EDGE_CORNER_RADIUS, 0);
return edge;
}
定制交互

呈现出来不难,业务的体现在于交互,客户需求要求虚拟主机不得超出云节点范围,超出时需要回撤操作,此外可以将一台虚拟机从一个子网移到另一个子网,另外还要控制路由的移动范围,限定在云节点的左边框上……

实现思路是通过交互监听,分别对移动(ELEMENT_MOVING),调整大小(RESIZING)等情况做处理,Qunee交互事件通常有三个状态:开始、进行时、结束,比如移动交互的三个过程:开始移动(ELEMENT_MOVE_START),移动中(ELEMENT_MOVING),完成移动(ELEMENT_MOVE_END),我们可以在开始时记录节点原始位置,结束时判断节点位置是否允许,如果不允许则作调整

var oldLocation = {};
graph.interactionDispatcher.addListener(function (evt) {
var data = evt.data;
if (evt.kind == Q.InteractionEvent.RESIZE_START) {
oldLocation[data.id] = {x: data.x, y: data.y, width: data.size.width, height: data.size.height};
}
if (evt.kind == Q.InteractionEvent.RESIZING) {
if (data == mainNode) {
label.updateLocation();
}
return;
}
if (evt.kind == Q.InteractionEvent.RESIZE_END) {
var oldBounds = oldLocation[data.id];
oldLocation = {};
if ((data != mainNode && isGroup(data) && groupIntersected(data)) || childrenOutParent(data)) {
data.setBounds(oldBounds);
}
if (data == mainNode) {
label.updateLocation();
}
return;
}
if (data.atLeft) {
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVING) {
data.updateLocation();
}
return;
}

if (evt.kind == Q.InteractionEvent.ELEMENT_MOVE_START) {  
    oldLocation[data.id] = {x: data.x, y: data.y};  
    return;  
}  
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVING) {  
    if (!isGroup(data)) {  
        var g = findGroup(evt.event);  
        highlight(g);  
    }  
    return;  
}  
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVE_END) {  
    highlight();  
    if (isGroup(data)) {  
        if (groupIntersected(data)) {  
            var old = oldLocation[data.id];  
            graph.moveElements([data], old.x - data.x, old.y - data.y);  
        }  
        return;  
    }  
    var g = findGroup(evt.event);  
    if (g) {  
        data.parent = data.host = g;  
        fixNode(data);  
    } else {  
        data.location = oldLocation[data.id];  
    }  
    oldLocation = {};  
}  

})
最终效果

VPC配置图www.szyoudun.com

继续阅读 »

云计算大行其道,上期开源中国的原创会就有好几位云计算专家演讲,从底层的虚拟化技术,到上层的云存储和应用API,耳濡目染,也受益匪浅,算是大势所趋,回头看看Qunee组件,借这个趋势,可以在云计算可视化上发挥作用,最近就有客户用Qunee实现VPC配置图,并对交互做了定制,细节不便多说,本文主要介绍Qunee交互扩展方面的思路

云计算大行其道,上期开源中国的原创会就有好几位云计算专家演讲,从底层的虚拟化技术,到上层的云存储和应用API,耳濡目染,也受益匪浅,算是大势所趋,回头看看Qunee组件,借这个趋势,可以在云计算可视化上发挥作用,最近就有客户用Qunee实现VPC配置图,并对交互做了定制,细节不便多说,本文主要介绍Qunee交互扩展方面的思路

VPC配置图

参考示例 – visualops

云平台可视化这块儿国外做的不错,有不少开放的示例可以学习和参考,客户看中了这家云管理系统http://www.visualops.io/ ,这个系统使用的是SVG技术,体验了一下,效果不错,参照着实现

从界面上看,一个云节点上有多个子网,每个子网内有多台虚拟主机,然后每个云节点有统一的路由Router管理(或者网关Gateway)

visualops

界面呈现

参照原型实现,使用Q.Path描出子网和云节点范围,虚拟机则用普通节点,连线使用正交连线类型,此外还有些外观配置,比如虚线,背景颜色,网格等,设置style或者css即可

创建矩形元素(子网、云节点)

function createRect(name, left, top, width, height, fillColor) {
var rect = graph.createNode(name, left, top);
rect.type = "rectGroup";
rect.anchorPosition = Q.Position.LEFT_TOP;
rect.image = Q.Shapes.getRect(0, 0, 100, 100);
rect.size = {width: width, height: height};
rect.setStyle(Q.Styles.IMAGE_BACKGROUND_COLOR, fillColor || Q.toColor(0x88FFFFFF));
rect.setStyle(Q.Styles.SHAPE_STROKE, 0);
rect.setStyle(Q.Styles.BORDER, 1);
rect.setStyle(Q.Styles.BORDER_COLOR, "#32c02f");
rect.setStyle(Q.Styles.BORDER_LINE_DASH, [5, 6]);
rect.setStyle(Q.Styles.LABEL_PADDING, 5);
rect.setStyle(Q.Styles.LABEL_ANCHOR_POSITION, Q.Position.LEFT_TOP);
rect.setStyle(Q.Styles.LABEL_POSITION, Q.Position.LEFT_TOP);
rect.setBounds = function (bounds) {
this.x = bounds.x;
this.y = bounds.y;
this.size = new Q.Size(bounds.width, bounds.height);
}
rect.getBounds = function () {
return new Q.Rect(this.x, this.y, this.size.width, this.size.height);
}
rect.inBounds = function (x, y) {
return this.getBounds().contains(x, y);
}
rect.intersectsRect = function (rect) {
return rect.intersectsRect(this.x, this.y, this.size.width, this.size.height);
}
rect.containsRect = function (rect) {
return Q.containsRect(this.x, this.y, this.size.width, this.size.height, rect.x, rect.y, rect.width, rect.height);
}
rect.updateBoundsByChildren = function () {
var bounds = new Q.Rect();
Q.forEachChild(this, function (child) {
bounds.add(graph.getUIBounds(child));
});
this.location = new Q.Point(bounds.x, bounds.y - 15);
this.size = new Q.Size(Math.max(200, bounds.width), Math.max(70, bounds.height + 15));
}
return rect;
}
注意到对Rect增加了一些标定节点范围、计算自身大小的方法,后面交互时会用到

创建虚拟主机

function createPC(name, x, y, parent) {
var node = graph.createNode(name, x, y);
node.image = Q.Graphs.server;
node.parent = node.host = parent;
node.zIndex = 10;
return node;
}
创建连接关系

function createEdge(from, to) {
var name = from.name + "->" + to.name;
var edge = graph.createEdge(name, from, to);
edge.edgeType = Q.Consts.EDGE_TYPE_VERTICAL_HORIZONTAL;
edge.setStyle(Q.Styles.EDGE_FROM_OFFSET, {x: 20});
edge.setStyle(Q.Styles.EDGE_CORNER_RADIUS, 0);
return edge;
}
定制交互

呈现出来不难,业务的体现在于交互,客户需求要求虚拟主机不得超出云节点范围,超出时需要回撤操作,此外可以将一台虚拟机从一个子网移到另一个子网,另外还要控制路由的移动范围,限定在云节点的左边框上……

实现思路是通过交互监听,分别对移动(ELEMENT_MOVING),调整大小(RESIZING)等情况做处理,Qunee交互事件通常有三个状态:开始、进行时、结束,比如移动交互的三个过程:开始移动(ELEMENT_MOVE_START),移动中(ELEMENT_MOVING),完成移动(ELEMENT_MOVE_END),我们可以在开始时记录节点原始位置,结束时判断节点位置是否允许,如果不允许则作调整

var oldLocation = {};
graph.interactionDispatcher.addListener(function (evt) {
var data = evt.data;
if (evt.kind == Q.InteractionEvent.RESIZE_START) {
oldLocation[data.id] = {x: data.x, y: data.y, width: data.size.width, height: data.size.height};
}
if (evt.kind == Q.InteractionEvent.RESIZING) {
if (data == mainNode) {
label.updateLocation();
}
return;
}
if (evt.kind == Q.InteractionEvent.RESIZE_END) {
var oldBounds = oldLocation[data.id];
oldLocation = {};
if ((data != mainNode && isGroup(data) && groupIntersected(data)) || childrenOutParent(data)) {
data.setBounds(oldBounds);
}
if (data == mainNode) {
label.updateLocation();
}
return;
}
if (data.atLeft) {
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVING) {
data.updateLocation();
}
return;
}

if (evt.kind == Q.InteractionEvent.ELEMENT_MOVE_START) {  
    oldLocation[data.id] = {x: data.x, y: data.y};  
    return;  
}  
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVING) {  
    if (!isGroup(data)) {  
        var g = findGroup(evt.event);  
        highlight(g);  
    }  
    return;  
}  
if (evt.kind == Q.InteractionEvent.ELEMENT_MOVE_END) {  
    highlight();  
    if (isGroup(data)) {  
        if (groupIntersected(data)) {  
            var old = oldLocation[data.id];  
            graph.moveElements([data], old.x - data.x, old.y - data.y);  
        }  
        return;  
    }  
    var g = findGroup(evt.event);  
    if (g) {  
        data.parent = data.host = g;  
        fixNode(data);  
    } else {  
        data.location = oldLocation[data.id];  
    }  
    oldLocation = {};  
}  

})
最终效果

VPC配置图www.szyoudun.com

收起阅读 »

php 建造者生成器模式学习笔记

适用场景:
1、 需要生成的产品对象有复杂的内部结构。
2、 需要生成的产品对象的属性相互依赖,生成器模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
使用效果:
1、 生成器模式的使用使得产品的内部表象可以独立的变化。使用生成器模式可以使客户端不必知道产品内部组成的细节。
2、 每一个Builder都相对独立,而与其它的Builder无关。
3、 模式所建造的最终产品更易于控制。

<?php
/**

  • Created by PhpStorm.
    */

/**具体产品角色 车

  • Class Car
    */
    class Car
    {
    public $_head;
    public $_engine;//引擎
    public $_tyre;//轮胎

function show()
{
echo "车头的颜色:{$this->_head}<br/>";
echo "引擎的品牌:{$this->_engine}<br/>";
echo "轮胎的品牌:{$this->_tyre}<br/>";
}
}

/**抽象车的建造者(生成器)

  • Class CarBuilder
    */
    abstract class CarBuilder
    {
    protected $_car;

function __construct()
{
$this->_car=new Car();
}

abstract function BuildHead();
abstract function BuildEngine();
abstract function BuildTyre();
abstract function GetCar();
}

/**具体车的建造者(生成器) 宝马

  • Class BMW
    */
    class BMW extends CarBuilder
    {

function BuildHead()
{
// TODO: Implement BuilderHead() method.
$this->_car->_head="Black";
}

function BuildEngine()
{
// TODO: Implement BuildEngine() method.
$this->_car->_engine="BMW";
}

function BuildTyre()
{
// TODO: Implement BuildTyre() method.
$this->_car->_tyre="BMW";
}

function GetCar()
{
// TODO: Implement GetCar() method.
return $this->_car;
}
}

/**别克

  • Class BuickBird
    */
    class BuickBird extends CarBuilder
    {

function BuildHead()
{
// TODO: Implement BuildHead() method.
$this->_car->_head="Red";
}

function BuildEngine()
{
// TODO: Implement BuildEngine() BMmethod.
$this->_car->_engine="Buick";//
}

function BuildTyre()
{
// TODO: Implement BuildTyre() method.
$this->_car->_tyre="Buick";
}

function GetCar()
{
// TODO: Implement GetCar() method.
return $this->_car;
}
}

/**指挥者

  • Class Director
    */
    class Director
    {
    /**
  • @param $_builder 建造者
  • @return mixed 产品类:车
    */
    function Construct($_builder)
    {
    $_builder->BuildHead();
    $_builder->BuildEngine();
    $_builder->BuildTyre();
    return $_builder->GetCar();
    }
    }www.szyoudun.com
继续阅读 »

适用场景:
1、 需要生成的产品对象有复杂的内部结构。
2、 需要生成的产品对象的属性相互依赖,生成器模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
使用效果:
1、 生成器模式的使用使得产品的内部表象可以独立的变化。使用生成器模式可以使客户端不必知道产品内部组成的细节。
2、 每一个Builder都相对独立,而与其它的Builder无关。
3、 模式所建造的最终产品更易于控制。

<?php
/**

  • Created by PhpStorm.
    */

/**具体产品角色 车

  • Class Car
    */
    class Car
    {
    public $_head;
    public $_engine;//引擎
    public $_tyre;//轮胎

function show()
{
echo "车头的颜色:{$this->_head}<br/>";
echo "引擎的品牌:{$this->_engine}<br/>";
echo "轮胎的品牌:{$this->_tyre}<br/>";
}
}

/**抽象车的建造者(生成器)

  • Class CarBuilder
    */
    abstract class CarBuilder
    {
    protected $_car;

function __construct()
{
$this->_car=new Car();
}

abstract function BuildHead();
abstract function BuildEngine();
abstract function BuildTyre();
abstract function GetCar();
}

/**具体车的建造者(生成器) 宝马

  • Class BMW
    */
    class BMW extends CarBuilder
    {

function BuildHead()
{
// TODO: Implement BuilderHead() method.
$this->_car->_head="Black";
}

function BuildEngine()
{
// TODO: Implement BuildEngine() method.
$this->_car->_engine="BMW";
}

function BuildTyre()
{
// TODO: Implement BuildTyre() method.
$this->_car->_tyre="BMW";
}

function GetCar()
{
// TODO: Implement GetCar() method.
return $this->_car;
}
}

/**别克

  • Class BuickBird
    */
    class BuickBird extends CarBuilder
    {

function BuildHead()
{
// TODO: Implement BuildHead() method.
$this->_car->_head="Red";
}

function BuildEngine()
{
// TODO: Implement BuildEngine() BMmethod.
$this->_car->_engine="Buick";//
}

function BuildTyre()
{
// TODO: Implement BuildTyre() method.
$this->_car->_tyre="Buick";
}

function GetCar()
{
// TODO: Implement GetCar() method.
return $this->_car;
}
}

/**指挥者

  • Class Director
    */
    class Director
    {
    /**
  • @param $_builder 建造者
  • @return mixed 产品类:车
    */
    function Construct($_builder)
    {
    $_builder->BuildHead();
    $_builder->BuildEngine();
    $_builder->BuildTyre();
    return $_builder->GetCar();
    }
    }www.szyoudun.com
收起阅读 »

php反射类 ReflectionClass使用例子

反射类是一个类的映射
namespace News;
class News{
public $newsid;
public function index(){
……
}
}
正常我们实例化一个类是这样: $News = new News\News();
如果我们要实例化News类的反射类是这样:$News = new \ReflectionClass(‘News\News’);
那么通过反射类实例化的类和普通类有什么不同呢?
通过反射类实例化的类我们可以获取这个这个类的详细信息,可以对类进行分析
例如:$News->getProperties()可以获取这个类的所有属性与方法。
array (size=1)
0 => & object(ReflectionProperty)[2]
public 'name' => string 'newsid' (length=6)
public 'class' => string 'News' (length=4)
getShortName() getName() getNamespaceName() 分别可以获得类名,带命名空间的类名,和命名空间的名称 News News\News News
ReflectionClass的一个应用就是在父类中获取子类的名称,从而针对不同的子类做不同的处理:
$reflection = new \ReflectionClass($this);
$class_name = $reflection->getShortName();
// check key
if (!key_exists($class_name, $this->configs)) {
return true;
}
// params
$params = $this->configs[$class_name];
return $this->_handle($params);
反射类的使用应该可以相当灵活,还有相当多的其他用途待发掘。www.qqfarms.cn

继续阅读 »

反射类是一个类的映射
namespace News;
class News{
public $newsid;
public function index(){
……
}
}
正常我们实例化一个类是这样: $News = new News\News();
如果我们要实例化News类的反射类是这样:$News = new \ReflectionClass(‘News\News’);
那么通过反射类实例化的类和普通类有什么不同呢?
通过反射类实例化的类我们可以获取这个这个类的详细信息,可以对类进行分析
例如:$News->getProperties()可以获取这个类的所有属性与方法。
array (size=1)
0 => & object(ReflectionProperty)[2]
public 'name' => string 'newsid' (length=6)
public 'class' => string 'News' (length=4)
getShortName() getName() getNamespaceName() 分别可以获得类名,带命名空间的类名,和命名空间的名称 News News\News News
ReflectionClass的一个应用就是在父类中获取子类的名称,从而针对不同的子类做不同的处理:
$reflection = new \ReflectionClass($this);
$class_name = $reflection->getShortName();
// check key
if (!key_exists($class_name, $this->configs)) {
return true;
}
// params
$params = $this->configs[$class_name];
return $this->_handle($params);
反射类的使用应该可以相当灵活,还有相当多的其他用途待发掘。www.qqfarms.cn

收起阅读 »