這個就是一個練手的基礎性的demo,不過也是有不少值得學習的東西的
效果以下
項目地址爲:https://github.com/h5weex/h5weex-example
多是我找到的項目比較少,不多有博主可以讓我吹爆它的彩虹屁的~
博主readme中的tnpm就按照平時的npm install就好,它還提到了一個
我以爲很是的有意思,weex的jsbundle用於客戶端運行,若是要用 web 的形式打開這個 weex 頁面,須要新建一個 html 文件,
把這個 jsbundle 文件以 script 腳本的方式引入。看連接
接下來咱們來看項目
先把.we文件變成.vue文件
接下來分析代碼
代碼爲css
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>h5weex</title> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-touch-fullscreen" content="yes" /> <meta name="format-detection" content="telephone=no, email=no" /> <style> html, body, #weex { width: 100%; height: 100%; background: #eeeeee; } </style> <!-- lib.flexible --> <script src="//g.alicdn.com/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> <script src="//g.alicdn.com/weex/weex-html5/0.3.5/weex.min.js"></script> </head> <body> <div id="weex"></div> <script> (function () { function getUrlParam (key) { var reg = new RegExp('[?|&]' + key + '=([^&]+)'); var match = location.search.match(reg); return match && match[1]; } var loader = getUrlParam('loader') || 'xhr'; var page = getUrlParam('_wx_tpl') || ''; if(page == ''){ var pagelist = ['datalist','iconfont','lazyload','require','sticky']; var htmlstr = '<h3 style="padding:10px;">該項目的頁面有:</h3><ul style="padding:10px;">'; for(var i in pagelist){ htmlstr += '<li style="height:30px;line-height:30px;"><a href="index.html?_wx_tpl=build/'+pagelist[i]+'.bundle.js">'+pagelist[i]+'.we</a></li>'; } htmlstr += '</ul>'; document.getElementById('weex').innerHTML = htmlstr; } else { window.weex.init({ appId: location.href, loader: loader, source: page, rootId: 'weex' }); } })(); </script> </body> </html>
這個詳情頁還有作下拉加載更多的功能哦
封裝了一個圖片和粉絲數目的組件,還能夠點擊跳轉到淘寶html
//account.vue <template> <div class="account-item" index="{{$index}}"> <div class="account-main"> <div class="account-logo" onclick="goTargetUrl"> <div class="account-logo-border"> <image class="account-logo-pic" src="{{logourl}}"></image> </div> </div> <div class="account-info" onclick="goTargetUrl"> <text class="desc account-name">{{name}}</text> <text class="desc account-doc">{{reason}}</text> <text class="desc account-fans">粉絲數:{{fans}}</text> </div> </div> </div> </template> <style> .account-item { flex-direction: column; width: 750; } .account-main { flex-direction: row; padding: 24; padding-left: 0; margin-left: 24; border-width: 0; border-style: solid; border-color: #E7E7E7; border-bottom-width: 1; } .account-logo-border { width: 104; height: 104; background-image: url("//gw.alicdn.com/tps/TB1KMYqNXXXXXcoXXXXXXXXXXXX-104-104.png"); } .account-logo-pic { width: 96; height: 96; margin: 4; align-items: center; justify-content: center; background-color: #cccccc; } .account-info { flex: 1; margin-left: 24; margin-right: 24; height: 104; } .desc { margin-bottom: 4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; lines: 1; } .account-name { margin-top: 4; font-size: 28; color: #3E3E3E; height: 34; font-weight: bold; } .account-doc { font-size: 24; color: #5F646E; height: 30; } .account-fans { font-size: 20; height: 26; color: #999; } </style> <script> module.exports = { data: { logourl: '', reason: '', name: '', fans: 1000, url: '' }, methods: { goTargetUrl: function(e) { require('@weex-module/event').openURL(this.url); } } } </script>
接下來分析詳情頁的代碼,裏面引用了weex的refresh和loading組件
完整代碼爲vue
//detail.vue <template> <list show-scrollbar="false" class="list" onloadmore="loadMore" loadmoreoffset="0"> <refresh class="refresh" display="{{showRefresh}}" onrefresh="onrefresh"> <text class="loading-text">{{refreshText}}</text> </refresh> <cell repeat={{itemList}} track-by="id"> <account append="tree" logourl="{{logourl}}" name="{{name}}" fans="{{fans}}" reason="{{reason}}" url="{{url}}"> </account> </cell> <loading class="loading" display="{{showLoading}}" onloading="onloading"> <loading-indicator class="loading-image" if="{{showLoadingImage}}"></loading-indicator> <text class="loading-text">{{loadingText}}</text> </loading> </list> </template> <style> .refresh { height: 120; width: 750; background-color: #ffffff; flex-direction: row; align-items: center; justify-content: center; } .list { flex-direction: column; background-color: #ffffff; width: 750; } .loading { height: 120; width: 750; margin-top: 20; background-color: #ffffff; flex-direction: row; align-items: center; justify-content: center; } .loading-text { text-align: center; color: #666666; font-size: 28; margin-left: 30; } .loading-image { height: 30; width: 30; color: #333333; } </style> <script> require('../c/account.vue'); </script> <script> module.exports = { data: { requesting: false, showRefresh: 'hide', refreshText: '下拉釋放刷新', showLoading: 'hide', showLoadingImage: true, loadingText: '數據加載中...', pageNum: 1, pageSize: 10, itemList: [] }, methods: { /** * 加載更多 */ loadMore: function () { console.log('onloadmore,this pageNum:', this.pageNum); var vm = this; //正在刷新的時候不響應loadmore if(vm.showRefresh == 'show'){ return; } vm.showLoading = 'show'; //最大加載50條 if(vm.pageNum >= 6){ vm.showLoadingImage = false; vm.loadingText = '沒有更多數據了'; setTimeout(function(){ vm.showLoading = 'hide'; }, 500); return; } vm.getData(); }, /** * 只有當loadmore不執行了,而且觸底了才觸發 */ onloading: function (e) { console.log('onloading'); var vm = this; vm.showLoading = 'show'; setTimeout(function() { vm.showLoading = 'hide'; }, 500); }, /** * 觸頂纔會觸發 */ onrefresh: function(e) { console.log('onrefresh'); var vm = this; vm.showRefresh = 'show'; //數據重置 vm.pageNum = 1; vm.itemList = []; vm.loadingText = '數據加載中...'; vm.showLoading = 'hide'; vm.showLoadingImage = true; //開始刷新 vm.getData(); }, /** * 請求接口獲取數據 */ getData: function() { if(this.requesting){return;} this.requesting = true; console.log('正在請求數據接口...this.pageNum:',this.pageNum); var vm = this; var originData = [].slice.call(vm.itemList); var tmp = []; var offset = (vm.pageNum-1) * vm.pageSize; for(var i = offset; i < offset + vm.pageSize; i++){ tmp.push({ id: i, logourl: '//gw.alicdn.com/tfscom/tuitui/TB1bA6gMXXXXXXmXFXXXXXXXXXX', name: 'name' + i, fans: 1000 + i, reason: '潮人最愛的女裝top紅人', url: '//shop.m.taobao.com/shop/shop_index.htm?user_id=2103587316&shop_id=111126855' }); } //模擬一個ajax請求的延遲返回數據結果 setTimeout(function(){ vm.pageNum ++; vm.itemList = originData.concat(tmp); vm.showLoading = 'hide'; vm.showRefresh = 'hide'; vm.requesting = false; console.log('this.itemList length:',vm.itemList.length); }, 500); } }, ready: function() { console.log('ready'); }, created: function (){ console.log('created'); this.getData(); } }; </script>
這個應該沒有乾貨html5
//iconfont.vue <template> <div class="container" data-role="iconfont"> <div class="wrapper" style="height: 80"> <text class="icon"></text> <text class="icon icon-small"></text> <text class="icon icon-middle"></text> <text class="icon icon-big"></text> </div> <div class="wrapper"> <text class="icon icon-fixed"></text> <text class="text">更多好貨</text> </div> <div class="wrapper center"> <text class="text">更多好貨</text> <text class="icon icon-fixed"></text> </div> <div class="wrapper right"> <text class="text">更多好貨</text> <text class="icon icon-fixed"></text> </div> </div> </template> <style> .icon { font-family: 'iconfont'; font-size: 40; } .icon-small { font-size: 50; } .icon-middle { font-size: 60; } .icon-big { font-size: 70; } .wrapper { flex-direction: row; height: 40; margin-top: 20; margin-bottom: 20; } .icon-fixed { margin-top: -8; margin-right: 5; color: #FF0000; } .text { font-size: 32; color: #FF0000; height: 32; line-height: 32; } .center { justify-content: center; } .right { justify-content: flex-end; } </style> <script> module.exports = { data: {}, methods: {}, created: function (){ //目前支持ttf、woff文件,不支持svg、eot類型 require('@weex-module/dom').addRule('fontFace', { 'fontFamily': 'iconfont', 'src': 'url("//at.alicdn.com/t/font_1474166554_8834667.ttf")' }); } }; </script>
這個的乾貨聽說是懶加載
這個是double-image組件git
//double-image.vue <template> <div class="wrapper" data-role="double_image"> <div repeat={{picUrlList}} class="url" onclick="goTargetUrl" url="{{url}}"> <image src="{{pic}}" class="image"></image> </div> </div> </template> <style> .wrapper { flex-direction: row; justify-content: space-between; width: 750; height: 224; margin-bottom: 18; padding-left: 18; padding-right: 18; padding-top: 18; padding-bottom: 18; background-color: #ffffff; box-sizing: border-box; } .url{ width: 345; height: 188; } .image{ width: 345; height: 188; } </style> <script> module.exports = { data : { picUrlList: [] }, methods: { goTargetUrl: function(e) { require('@weex-module/event').openURL(e.target.attr.url); }, render: function(ds) { //console.log('ds:', ds); this.picUrlList = ds; } } }; </script>
//lazyload.vue <template> <scroller class="container" loadmoreoffset="960" onloadmore="loadMore" show-scrollbar="false" onappear="appear" ondisappear="disappear"> <double-image id="component-0"></double-image> <double-image id="component-1"></double-image> <double-image id="component-2"></double-image> <double-image id="component-3"></double-image> <double-image id="component-4"></double-image> <double-image id="component-5"></double-image> <double-image id="component-6"></double-image> <double-image id="component-7"></double-image> <double-image id="component-8"></double-image> <double-image id="component-9"></double-image> <double-image id="component-10"></double-image> <double-image id="component-11"></double-image> <double-image id="component-12"></double-image> <double-image id="component-13"></double-image> <double-image id="component-14"></double-image> <double-image id="component-15"></double-image> <double-image id="component-16"></double-image> <double-image id="component-17"></double-image> <double-image id="component-18"></double-image> <double-image id="component-19"></double-image> </scroller> </template> <style> .container{ width: 750px; background-color: #eeeeee; display: flex; flex-direction: column; padding-bottom: 50px; } </style> <script> require('../c/double-image.we'); module.exports = { data: { pointer: 0, shouldStop: true, picUrlList: [ { pic: "https://gw.alicdn.com/imgextra/i2/263662065/TB2VVk4jFXXXXbWXpXXXXXXXXXX_!!263662065.jpg", url: "//h5.m.taobao.com/wirelessshop/decorator/view.html?userId=123&pageId=46&ttt=111&isMock=true#222222" }, { pic: "https://gw.alicdn.com/tps/i3/TB1RqA7HFXXXXbbXFXXrVZt0FXX-640-200.jpg", url: "//h5.wapa.taobao.com/wirelessshop/decorator/view_h5.html?userId=123&pageId=46&ttt=111&isMock=true#222222" } ] }, methods: { appear: function () { this.$broadcast('sliderStart'); console.log('appear'); }, disappear: function () { this.$broadcast('sliderStop'); console.log('disappear'); }, loadMore: function (e) { console.log('loadmore'); if(this.shouldStop) { return; } for(var i = 0; i < 10; i++) { var compVm = this.$vm('component-' + this.pointer); if(!compVm) { this.shouldStop = !0; return; } if(!compVm.render) { this.pointer++; continue; } compVm.render(this.picUrlList); this.pointer++; } } }, ready: function (){ console.log('ready'); this.shouldStop = false; for(var i = 0; i < 10; i ++) { var compVm = this.$vm('component-' + i); //console.log(compVm); if(!compVm) { this.pointer++; continue; } if(!compVm.render) { this.pointer++; continue; } compVm.render(this.picUrlList); this.pointer++; } } }; </script>
這個裏面用了兩個組件github
//itemlist.vue <template> <div data-role="itemlist"> <div class="wrapper" if="{{mds.itemList.length}}"> <div repeat="{{mds.itemList}}" url="{{url}}" class="item-url" onclick="goTargetUrl"> <image src="{{pic_url}}" class="item-img"></image> <div class="item-info"> <text class="item-name">{{title}}</text> <div class="item-price"> <text class="item-price-text">¥</text> <text class="item-price-text big">{{price.split('.')[0]}}</text> <text class="item-price-text">{{price.split('.').length > 1 ? '.' + price.split('.')[1] : ''}}</text> </div> </div> </div> </div> </div> </template> <style> .wrapper { width: 750; padding-left: 18; padding-right: 18; margin-bottom: 18; box-sizing: border-box; flex-direction: row; justify-content: space-between; } .item-url { width: 230; background-color: #ffffff; flex-direction: column; justify-content: space-between; } .item-img { width: 230; height: 230; } .item-info { width: 230; padding-left: 10; padding-right: 10; padding-bottom: 18; box-sizing: border-box; flex-direction: column; } .item-name { line-height: 56; height: 56; flex-direction: row; color: #000000; font-size: 28; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; lines: 1; } .item-price { flex-direction: row; align-items: flex-end; height: 40; } .item-price-text { color: #e61616; font-size: 24; } .big { font-size: 32; font-weight: bold; } </style> <script> module.exports = { data: { mds: { dataParams: { "catId": "-1" }, itemList: [], }, gdc: { "ownerId": 2202220535 } }, methods: { goTargetUrl: function(e) { require('@weex-module/event').openURL(e.target.attr.url); }, render: function(ds, gd){ var vm = this; if(ds){ vm.mds = ds; } if(gd){ vm.gdc = gd; } } }, ready: function() { console.log('ready:', this.mds); } }; </script>
promotion組件web
//promotion.vue <template> <div class="wrapper" data-role="promotion" onclick="goTargetUrl"> <image src="//img.alicdn.com/tps/TB1V2AeNXXXXXbXXFXXXXXXXXXX-714-180.png" class="image"></image> <div class="container"> <div class="price"> <text class="priceText small">¥</text> <text class="priceText">{{mds.ticketDesc}}</text> <image class="priceImg" src="//img.alicdn.com/tps/TB1gEj7NXXXXXc7XVXXXXXXXXXX-201-36.png"></image> </div> <div class="detail"> <text class="desc">可疊加,可跨店使用</text> <text class="desc">使用條件見商品詳情頁滿減規則</text> </div> </div> </div> </template> <style> .wrapper { width: 750; box-sizing: border-box; margin-bottom: 18; padding-left: 18; padding-right: 18; position: relative; } .image{ width: 714; height: 180; } .container{ flex-direction: column; box-sizing: border-box; width: 714; height: 180; position: absolute; padding-left: 36; left: 0; top: 0; } .price{ height: 80; flex-direction: row; align-items: flex-end; } .priceText { color: #ffffff; font-size: 48; font-weight: bold; } .priceImg { width: 201; height: 36; margin-left: 20; } .small { font-size: 32; } .detail{ width: 354; height: 68; margin-top: 20; flex-direction: column; box-sizing: border-box; } .desc{ width: 354; height: 34; line-height: 34; color: #B96200; font-size: 24; } .time{ width: 354; height: 26; flex-direction: row; } .timeText{ color: #ffffff; font-size: 24; } </style> <script> module.exports = { data: { mds: { ticketUrl: '', ticketDesc: '100' }, gdc: {} }, methods: { goTargetUrl: function() { require('@weex-module/event').openURL(this.mds.ticketUrl); }, render: function(ds){ if(ds){ this.mds.ticketUrl = ds.ticketUrl; this.mds.ticketDesc = ds.ticketDesc; } } }, ready: function() { console.log('ready:', this.mds); } }; </script>
完整代碼爲ajax
<template> <scroller show-scrollbar="false"> <itemlist mds="{{dataSource[0]}}" gdc="{{golbalData}}"></itemlist> <promotion mds="{{dataSource[1]}}" gdc="{{golbalData}}"></promotion> </scroller> </template> <script> require('../c/itemlist.we'); require('../c/promotion.we'); </script> <script> module.exports = { data: { golbalData: { ownerId: 2202220535 }, dataSource: [ { itemList: [ { title:"測試寶貝1測試寶貝1測試寶貝1測試寶貝1", pic_url:"//gw.alicdn.com/bao/uploaded/i1/2202220535/TB2du8TqFXXXXa1XpXXXXXXXXXX_!!2202220535.jpg", url:"https://www.taobao.com/", price:"11.50" }, { title:"測試寶貝2測試寶貝1測試寶貝1測試寶貝1", pic_url:"//gw.alicdn.com/bao/uploaded/i2/2202220535/TB25odWqFXXXXaxXpXXXXXXXXXX_!!2202220535.jpg", url:"https://www.taobao.com/", price:"22.30" }, { title:"測試寶貝3測試寶貝1測試寶貝1測試寶貝1", pic_url:"//gw.alicdn.com/bao/uploaded/i1/2202220535/TB2du8TqFXXXXa1XpXXXXXXXXXX_!!2202220535.jpg_200x200", url:"https://www.taobao.com/", price:"22.00" } ] }, { ticketUrl: 'http://www.taobao.com', ticketDesc: '100' } ] }, created: function (){ var vm = this; }, ready: function () { console.log(this.dataSource[0],this.dataSource[1]); } }; </script>
item組件npm
<template> <div class="item" data-role="item" onclick="goTargetUrl"> <image src="{{pic_url}}" class="item-img"></image> <div class="item-info"> <text class="item-name">{{title}}</text> <div class="item-price"> <text class="item-price-text">¥</text> <text class="item-price-text big">{{price.split('.')[0]}}</text> <text class="item-price-text">{{price.split('.').length > 1 ? '.' + price.split('.')[1] : ''}}</text> </div> </div> </div> </template> <style> .item { width: 250; background-color: #ffffff; flex-direction: column; justify-content: space-between; } .item-img { width: 230; height: 230; } .item-info { width: 230; padding-left: 10; padding-right: 10; padding-bottom: 18; box-sizing: border-box; flex-direction: column; } .item-name { line-height: 56; height: 56; flex-direction: row; color: #000000; font-size: 28; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; lines: 1; } .item-price { flex-direction: row; align-items: flex-end; height: 40; } .item-price-text { color: #e61616; font-size: 24; } .big { font-size: 32; font-weight: bold; } </style> <script> module.exports = { data: { title: '測試寶貝,勿拍', url: '//detail.m.tmall.com/item.htm?id=538817029299', pic_url: '//gw.alicdn.com/tfscom/tuitui/i4/TB1g4hXNXXXXXcVXXXXXXXXXXXX_!!0-item_pic.jpg', price: '100.00' }, methods: { goTargetUrl: function() { require('@weex-module/event').openURL(this.url); } }, created: function() { } }; </script>
完整代碼爲segmentfault
<template> <list show-scrollbar="false" class="container"> <header class="title"> <text class="title-text">熱門榜單</text> <image class="title-image" src="//gw.alicdn.com/tps/i2/T11ftRFpXaXXa8IXfX-14-26.png"></image> </header> <cell class="itemlist"> <item></item> <item></item> <item></item> <item></item> <item></item> <item></item> </cell> <header class="title"> <text class="title-text">熱門榜單</text> <image class="title-image" src="//gw.alicdn.com/tps/i2/T11ftRFpXaXXa8IXfX-14-26.png"></image> </header> <cell class="itemlist"> <item></item> <item></item> <item></item> <item></item> <item></item> <item></item> </cell> <header class="title"> <text class="title-text">熱門榜單</text> <image class="title-image" src="//gw.alicdn.com/tps/i2/T11ftRFpXaXXa8IXfX-14-26.png"></image> </header> <cell class="itemlist"> <item></item> <item></item> <item></item> <item></item> <item></item> <item></item> </cell> </list> </template> <style> .container { width: 750; background-color: #eeeeee; margin-bottom: 28; } .title { flex-direction: row; justify-content: space-between; align-items: center; width: 750; height: 88; padding-left: 18; padding-right: 18; background-color: #ffffff; border-width: 0; border-style: solid; border-color: #cccccc; border-top-width: 1; border-bottom-width: 1; box-sizing: border-box; } .title-image { width: 14; height: 26; justify-content: center; } .title-text { width: 700; height: 88; justify-content: center; font-size: 32; color: #000000; } .itemlist { width: 750; padding-top: 18; margin-bottom: 18; background-color: #ffffff; box-sizing: border-box; flex-direction: row; flex-wrap: wrap; border-width: 0; border-style: solid; border-color: #cccccc; border-bottom-width: 1; } </style> <script> require('../c/item.we'); </script> <script> module.exports = { data: { }, methods: { }, created: function (){ var vm = this; } }; </script>