摘要:以下會(huì)以其中一個(gè)以公積金頁面開發(fā)項(xiàng)目作為例子,介紹移動(dòng)端的一些常見問題和使用作為進(jìn)行多頁開發(fā)的經(jīng)驗(yàn)。所以要想在微信開發(fā)調(diào)試工具中獲取,我們需要使用一種叫做內(nèi)網(wǎng)穿透的工具。
兩年前剛接觸移動(dòng)端開發(fā),剛開始比較疑惑,每次遇到問題都是到社區(qū)里提問或者吸取前輩的經(jīng)驗(yàn)分享,感謝熱衷于分享的開發(fā)者為前端社區(qū)帶來欣欣向上的生命力。本文結(jié)合先前寫的文章和開發(fā)經(jīng)驗(yàn)分享給大家,希望也能幫助剛步入移動(dòng)端開發(fā)的新人解惑。以下會(huì)以其中一個(gè)以公積金頁面開發(fā)項(xiàng)目作為例子,介紹移動(dòng)端的一些常見問題和使用Vuejs作為lib進(jìn)行多頁開發(fā)的經(jīng)驗(yàn)。
在項(xiàng)目中移動(dòng)端最常用的自適應(yīng)布局方案就是flexbox結(jié)合rem。規(guī)范的分欄式使用flexbox,其他大部分不規(guī)則視圖使用rem,對(duì)于rem最常用的方案就是淘寶開源的可伸縮布局方案。
根據(jù)設(shè)備設(shè)備像素比設(shè)置scale的值(scale = 1 / deviceRatio),這樣可以保持視口device-width始終等于設(shè)備物理像素,接著根據(jù)屏幕大小動(dòng)態(tài)計(jì)算根字體大小,具體是將屏幕劃分為100等分,每份為a,1rem就等于10a。
標(biāo)注通常我們會(huì)拿到750寬的設(shè)計(jì)稿,這是基于iPhone6的物理分辨率。有的設(shè)計(jì)師也許會(huì)偷懶,設(shè)計(jì)圖上面沒有任何的標(biāo)注,如果我們邊開發(fā)邊量尺寸,無疑效率是比較低的。要么讓設(shè)計(jì)師標(biāo)注上,要么自食其力。
如果設(shè)計(jì)師實(shí)在沒有時(shí)間,推薦使用markman進(jìn)行標(biāo)注,免費(fèi)版閹割了一些功能(比如無法保存本地)不過基本滿足了我們的需求了。
后來我發(fā)現(xiàn)比markman更好的標(biāo)注工具PxCook,該工具可以顯示PSD設(shè)計(jì)圖中的圖層的樣式代碼,對(duì)于前端來說簡(jiǎn)直方便極了。
標(biāo)注完成后開始寫我們的樣式,使用了淘寶的lib-flexible庫之后,我們的根字體基準(zhǔn)值就為750/100*10 = 75px。此時(shí)我們從圖中若某個(gè)標(biāo)注為100px,那么css中就應(yīng)該設(shè)置為100/75 = 1.333333rem。所以為了提高開發(fā)效率,可以使用px轉(zhuǎn)化為rem的插件。下面是sublimeText和Vscode的轉(zhuǎn)換插件:
px轉(zhuǎn)rem插件sublimeText插件:rem-unit
Vscode插件: cssrem
使用rem的幾點(diǎn)總結(jié)在所有的單位中,font-size推薦使用px,然后結(jié)合媒體查詢進(jìn)行重要節(jié)點(diǎn)的控制,這樣可以滿足突出或者弱化某些字體的需求,而非整體調(diào)整。
眾向的單位可以全部使用px,橫向的使用rem,因?yàn)橐苿?dòng)設(shè)備寬度有限,而高度可以無限向下滑動(dòng)。但這也有特例,比如對(duì)于一些活動(dòng)注冊(cè)頁面,需要在一屏幕內(nèi)完全顯示,沒有下拉,這時(shí)候所有眾向或者橫向都應(yīng)該使用rem作為單位。如圖:
左圖的表單高度單位由于下邊空距較大,使用px在不同屏幕顯示更加;而右邊的活動(dòng)注冊(cè)頁由于不能出現(xiàn)滾動(dòng)條,所有的眾向高度、margin、padding都應(yīng)該使用rem。
border、box-shadow、border-radius等一些效果應(yīng)該使用px作為單位。
手機(jī)狀態(tài)欄和瀏覽器導(dǎo)航欄的影響之前發(fā)布的文章中,有個(gè)SF的前端小伙伴提出的問題:
文中作者有重點(diǎn)強(qiáng)調(diào)布局全部鋪滿,和下方與很多空隙的處理方案是不同的,在工作中我遇到這種情況,設(shè)計(jì)師的設(shè)計(jì)稿寬度為750×1334,但實(shí)際的展示高度并沒有那么多,因?yàn)樯戏接袑?dǎo)航欄還包括手機(jī)自己的狀態(tài)欄展示,所以整體高度就達(dá)不到750,但是設(shè)計(jì)師設(shè)計(jì)稿是嚴(yán)格按照750進(jìn)行設(shè)計(jì)的,這種情況下使用rem,嚴(yán)格按照設(shè)計(jì)師尺寸進(jìn)行還原就會(huì)出現(xiàn)屏幕出現(xiàn)滾動(dòng)條情況,請(qǐng)問針對(duì)這種情況您是怎么處理的?是從設(shè)計(jì)稿上規(guī)范,還是從開發(fā)上有相應(yīng)的措施
依舊以我的分享界面為例:
展示高度不同通常發(fā)生在微信及瀏覽器端,因?yàn)榍罢邲]有地址欄和工具欄,這樣顯示高度通常會(huì)和設(shè)計(jì)師設(shè)計(jì)的視圖吻合。那如果按照純padding,margin即使全部使用rem,在瀏覽器端依舊會(huì)超出一屏高度,對(duì)于分享頁面這種不是我們想要看到的。這時(shí)候就要做出取舍,我對(duì)主體區(qū)域采用絕對(duì)定位,這樣上面間隙雖然小,不過仍能保持在一個(gè)屏幕高度顯示。若采用margin padding在設(shè)置,必然已出現(xiàn)滾動(dòng)條。當(dāng)然這樣的前提是依賴設(shè)計(jì)圖的,通常設(shè)計(jì)師會(huì)為了空間感有保留一定的間隙,也不會(huì)將主要對(duì)象高度設(shè)的過高,否則太撐滿也不好看,開發(fā)上如果設(shè)計(jì)圖寬高沒有在一定界限之內(nèi),超出也無法避免,不過我們這種分享界面通常是通過微信分享好友,通過瀏覽器打開的視圖效果出現(xiàn)滾動(dòng)條其實(shí)也不怎么影響不是么?
下面附上微信端和瀏覽器端的效果圖:
微信端:
瀏覽器端:
Vuejs作為lib開發(fā)移動(dòng)端頁面 為何不使用SPA模式一般移動(dòng)端使用vue是為了數(shù)據(jù)交互頻繁而且快速開發(fā)的頁面,為什么不使用單頁SPA開發(fā)模式,原因大概幾點(diǎn)。
為了快速開發(fā),快速上線
項(xiàng)目其他成員不熟悉SPA,不熟悉webpack
參與項(xiàng)目時(shí)項(xiàng)目已使用多頁開發(fā),短時(shí)間無法重構(gòu)
拋開使用單頁的架構(gòu),開發(fā)多頁應(yīng)用時(shí),一個(gè)頁面交互邏輯與一個(gè)Vue實(shí)例對(duì)應(yīng)。
基于接口返回?cái)?shù)據(jù)的屬性注入"基于接口返回?cái)?shù)據(jù)的屬性注入"是個(gè)人創(chuàng)建的話術(shù),拋開此概念,先說一下表單數(shù)據(jù)的綁定方式。
表單的數(shù)據(jù)綁定一個(gè)重要的點(diǎn)是有幾份表單就分開幾個(gè)表單對(duì)象進(jìn)行數(shù)據(jù)綁定。
以上圖公積金查詢?yōu)槔捎诓煌鞘袝?huì)有不同的查詢要素,可能登陸方式只有一種,也可能有幾種。比如上圖有三種登陸方式,在使用vue布局時(shí),有兩種方案。
1、 只建立一個(gè)表單用于數(shù)據(jù)綁定,點(diǎn)擊按鈕觸發(fā)判斷
2、有幾種登陸方式建立幾個(gè)表單,用一個(gè)字段標(biāo)識(shí)當(dāng)前顯示的表單
由于使用第三方的接口,一開始也沒有先進(jìn)行接口返回?cái)?shù)據(jù)結(jié)構(gòu)的查看,采用了第一種錯(cuò)誤的方式,錯(cuò)誤一是每種登陸方式下面的登陸要素的數(shù)量也不同,錯(cuò)誤二是數(shù)據(jù)綁定在同一個(gè)表單data下,當(dāng)用戶在用戶名登陸方式輸入用戶名密碼后,切換到客戶號(hào)登陸方式,就會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)亂的情況。
解決完布局問題后,我們需要根據(jù)設(shè)計(jì)圖定義一些狀態(tài),比如當(dāng)前登陸方式的切換、同意授權(quán)狀態(tài)的切換、按鈕是否可以點(diǎn)擊的狀態(tài)、是否處于請(qǐng)求中的狀態(tài)。當(dāng)然還有一些app穿過來的數(shù)據(jù),這里就忽略了。
data: { tags: { arr: [""], activeIndex: 0 }, isAgreeProxy: true, isLoading: false }
接著審查一下接口返回的數(shù)據(jù),推薦使用chrome插件postman,比如呼和浩特的登陸要素如下:
{ "code": 2005, "data": [ { "name": "login_type", "label": "身份證號(hào)", "fields": [ { "name": "user_name", "label": "身份證號(hào)", "type": "text" }, { "name": "user_pass", "label": "密碼", "type": "password" } ], "value": "1" }, { "name": " login_type", "label": "公積金賬號(hào)", "fields": [ { "name": "user_name", "label": "公積金賬號(hào)", "type": "text" }, { "name": "user_pass", "label": "密碼", "type": "password" } ], "value": "0" } ], "message": "登錄要素請(qǐng)求成功" }
可以看到呼和浩特有兩種授權(quán)登陸方式,我們?cè)赿ata中定義了一個(gè)loginWays,初始為空數(shù)組,接著methods中定義一個(gè)請(qǐng)求接口的函數(shù),里面就是基于返回?cái)?shù)據(jù)的基礎(chǔ)上為上面fields對(duì)象注入一個(gè)input字段用于綁定,這就是所謂的基于接口返回?cái)?shù)據(jù)的屬性注入。
methods: { queryloginWays: function(channel_type, channel_code) { var params = new URLSearchParams(); params.append("channel_type", channel_type); params.append("channel_code", channel_code); axios.post(this.loginParamsProxy, params) .then(function(res) { console.log(res); var code = res.code || res.data.code; var msg = res.message || res.data.message; var loginWays = res.data.data ? res.data.data : res.data; // 查詢失敗 if (code != 2005) { alert(msg); return; } // 添加input字段用于v-model綁定 loginWays.forEach(function(loginWay) { loginWay.fields.forEach(function(field) { field.input = ""; }) }) this.loginWays = loginWays; this.tags.arr = loginWays.map(function(loginWay) { return loginWay.label; }) }.bind(this)) } }
即使返回的數(shù)據(jù)有我們不需要的數(shù)據(jù)也沒有關(guān)系,這樣保證我們不會(huì)遺失進(jìn)行下一步登陸所需要的數(shù)據(jù)。
這樣多個(gè)表單綁定數(shù)據(jù)問題解決了,那么怎么進(jìn)行頁面間數(shù)據(jù)傳遞?如果是app傳過來,那么通常使用URL拼接的方式,使用window.location.search獲得queryString后再進(jìn)行截??;如果通過頁面套入javaWeb中,那么直接使用"${字段名}"就能獲取,注意要js中獲取java字段需要加雙引號(hào)。
computed: { // 真實(shí)姓名 realName: function() { return this.getQueryVariable("name") || "" }, // 身份證 identity: function() { return parseInt(this.getQueryVariable("identity")) || "" }, /*If javaWeb realName: function() { return this.getQueryVariable("name") || "" }, identity: function() { return parseInt(this.getQueryVariable("identity")) || "" }*/ }, methods: { getQueryVariable: function(variable) { var query = window.location.search.substring(1); var vars = query.split("&"); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split("="); if (decodeURIComponent(pair[0]) == variable) { return decodeURIComponent(pair[1]); } } console.log("Query variable %s not found", variable); } }關(guān)于前端跨域調(diào)試
在進(jìn)行接口請(qǐng)求時(shí),我們的頁面通常是在sublime的本地服務(wù)器或者vscode本地服務(wù)器預(yù)覽,所以請(qǐng)求接口會(huì)遇到跨域的問題,如果使用Gulp進(jìn)行打包,可以使用插件http-proxy-middleware,或者使用nginx。
使用Gulp在項(xiàng)目構(gòu)建的時(shí)候通常我們?cè)创a會(huì)放在src文件夾下,然后使用gulp進(jìn)行代碼的壓縮、合并、圖片的優(yōu)化(根據(jù)需要)等等,我們會(huì)使用gulp。
解決跨域的問題可以用gulp-connect結(jié)合http-proxy-middleware,此時(shí)我們?cè)趃ulp-connect中的本地服務(wù)器進(jìn)行預(yù)覽調(diào)試。
gulpfile.js如下: 開發(fā)過程使用gulp server:dev命令,監(jiān)聽文件改動(dòng)并使用livereload刷新,并且代理src目錄;使用gulp命令進(jìn)行打包;使用gulp server:dist代理dist生產(chǎn)目錄。
var gulp = require("gulp"); var concat = require("gulp-concat"); var uglify = require("gulp-uglify"); var autoprefixer = require("gulp-autoprefixer"); var useref = require("gulp-useref"); var connect = require("gulp-connect"); var proxyMiddleware = require("http-proxy-middleware"); // 開發(fā)跨域代理 將localhost:8088/api 映射到 https://api.xxxxx.com/ gulp.task("server:dev", ["listen"], function() { var middleware = proxyMiddleware(["/api"], { target: "https://api.xxxxx.com/", changeOrigin: true, pathRewrite: { "^/api": "/" } }); connect.server({ root: env == "dev" ? "./src" : "./dist", port: 8088, livereload: true, middleware: function(connect, opt) { return [middleware] } }); }); // 打包后跨域代理 gulp.task("server:dist", ["listen"], function() { var middleware = proxyMiddleware(["/api"], { target: "https://api.xxxxx.com/", changeOrigin: true, pathRewrite: { "^/api": "/" } }); connect.server({ root: "./dist", port: 8088, livereload: true, middleware: function(connect, opt) { return [middleware] } }); }); gulp.task("html", function() { gulp.src("src/*.html") .pipe(useref()) .pipe(gulp.dest("dist")); }); gulp.task("css", function() { gulp.src("src/css/main.css") .pipe(concat("main.css")) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(gulp.dest("dist/css/")); gulp.src("src/css/share.css") .pipe(concat("share.css")) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(gulp.dest("dist/css/")); gulp.src("src/vendors/css/*.css") .pipe(concat("vendors.min.css")) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(gulp.dest("dist/vendors/css")); return gulp }); gulp.task("js", function() { return gulp.src("src/vendors/js/*.js") .pipe(concat("vendors.min.js")) .pipe(uglify()) .pipe(gulp.dest("dist/vendors/js")); }); gulp.task("img", function() { gulp.src("src/imgs/*") .pipe(gulp.dest("dist/imgs")); }); gulp.task("listen", function() { gulp.watch("./src/css/*.css", function() { gulp.src(["./src/css/*.css"]) .pipe(connect.reload()); }); gulp.watch("./src/js/*.js", function() { gulp.src(["./src/js/*.js"]) .pipe(connect.reload()); }); gulp.watch("./src/*.html", function() { gulp.src(["./src/*.html"]) .pipe(connect.reload()); }); }); gulp.task("default", ["html", "css", "js", "img"]);使用nginx
在nginx配置使用proxy_pass,需要注意一點(diǎn):
如果在proxy_pass后面的url加/,表示絕對(duì)根路徑;如果沒有/,表示相對(duì)路徑,把匹配的路徑部分也給代理走。
server { listen 80; server_name localhost; root [Your project root]; index index.html index.htm default.html default.htm; location ^~/api { proxy_pass https://api.xxxxx.com/; } }公眾號(hào)網(wǎng)頁的調(diào)試
如果你開發(fā)的H5基于微信jsSDK,你一定接觸過微信授權(quán)域名,微信會(huì)將授權(quán)數(shù)據(jù)傳給一個(gè)回調(diào)頁面,而回調(diào)頁面必須在你配置的域名下(含子域名)。比如我們獲取用戶的openid操作。而微信配置域名回去該域名根目錄下檢測(cè)一個(gè)xxx_verify_xxx.txt文件,確保該域名是屬于你的。
所以要想在微信開發(fā)調(diào)試工具中獲取openid,我們需要使用一種叫做內(nèi)網(wǎng)穿透的工具。下面是自己比較常用的兩個(gè)工具:
ngrok
花生殼
ngrokngrok執(zhí)行命令
ngrok -config ngrok.cfg start web
在ngrok.exe目錄需要一個(gè)配置文件ngrok.cfg
以下是配置示例:
server_addr: "tunnel.cn:4443" trust_host_root_certs: false tunnels: web: subdomain: "xxx" proto: http: 8086 https: 8086
啟動(dòng)后xxx.tunnel.cn:4443會(huì)指向你本地的8086端口,將xxx_verify_xxx.txt文件放到8086端口根目錄即可配置授權(quán)域名成功。
花生殼花生殼免費(fèi)版對(duì)于個(gè)人開通僅需6元,然后每月會(huì)提供給你1G的流量,免費(fèi)版不支持80端口,最多支持兩個(gè)域名,需要下載桌面客戶端。
添加域名映射很簡(jiǎn)單,免費(fèi)版無法配置自定義域名,由花生殼自動(dòng)生成。
配置成功后啟動(dòng)客戶端可查看當(dāng)前的狀態(tài)
感謝閱讀,歡迎任何形式的技術(shù)提問和交流!歡迎關(guān)注公眾號(hào)前端新視界,把握技術(shù)前沿資訊。
主頁:huzerui.com
知乎:hzr
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95744.html
摘要:年前放假的最后一天,我們上線了獨(dú)家記憶活動(dòng)宣傳頁。微信分享主要代碼參考獨(dú)家記憶當(dāng)時(shí)光凝固,當(dāng)回憶定格。這是屬于我和的獨(dú)家記憶。 年前放假的最后一天,我們上線了「My Flyme 獨(dú)家記憶」 H5 活動(dòng)宣傳頁。 因種種原因,直到放假前幾天,才突然要求我們參與并開始項(xiàng)目的前端部分。此時(shí)大概的情況是:所有數(shù)據(jù)已計(jì)算完畢;后端接口已完成待聯(lián)調(diào);交互視覺只出了不到四分之一(一共二十多個(gè)頁面);我...
摘要:年前放假的最后一天,我們上線了獨(dú)家記憶活動(dòng)宣傳頁。微信分享主要代碼參考獨(dú)家記憶當(dāng)時(shí)光凝固,當(dāng)回憶定格。這是屬于我和的獨(dú)家記憶。 年前放假的最后一天,我們上線了「My Flyme 獨(dú)家記憶」 H5 活動(dòng)宣傳頁。 因種種原因,直到放假前幾天,才突然要求我們參與并開始項(xiàng)目的前端部分。此時(shí)大概的情況是:所有數(shù)據(jù)已計(jì)算完畢;后端接口已完成待聯(lián)調(diào);交互視覺只出了不到四分之一(一共二十多個(gè)頁面);我...
摘要:例如改成例如改成以上兩種開發(fā)方式都可以結(jié)合原生平臺(tái)打包成獨(dú)立應(yīng)用。 繼上一篇一張腦圖看懂BUI Webapp移動(dòng)快速開發(fā)框架【上】--框架與工具、資源 大綱 在線查看大綱 思路更佳清晰 1. 框架設(shè)計(jì) 框架介紹 簡(jiǎn)介 BUI 是用來快速構(gòu)建界面交互的UI交互框架, 專注webapp開發(fā), 開發(fā)者只需關(guān)注業(yè)務(wù)的開發(fā), 界面的布局及交互交給BUI, 開發(fā)出來的應(yīng)用, 可以嵌入平臺(tái) ( Li...
閱讀 1020·2021-11-15 18:06
閱讀 2386·2021-10-08 10:04
閱讀 2673·2019-08-28 18:03
閱讀 923·2019-08-26 13:42
閱讀 1943·2019-08-26 11:31
閱讀 2447·2019-08-23 17:13
閱讀 950·2019-08-23 16:45
閱讀 2081·2019-08-23 14:11