前言: 產品背景介紹 我所做的這個項目,剛開始是沒有移動端需求的,等PC端做完了上線使用了幾個月後,突然有一天產品經理找到我說是要做一個在PC端添加一個快速註冊入口,用手機微信掃二位碼進入移動端註冊頁面,用戶註冊。 所以本次需求就是在PC端添加一個tool-tip氣泡型彈出二維碼,再開發一個移動端註 ...
前言:
產品背景介紹
我所做的這個項目,剛開始是沒有移動端需求的,等PC端做完了上線使用了幾個月後,突然有一天產品經理找到我說是要做一個在PC端添加一個快速註冊入口,用手機微信掃二位碼進入移動端註冊頁面,用戶註冊。
所以本次需求就是在PC端添加一個tool-tip氣泡型彈出二維碼,再開發一個移動端註冊頁面。
起初我是在PC項目中引入vant新加了一個模塊來存放移動註冊頁面和註冊成功頁面的,然後想使用postcss-px-to-viewport的exclude和include屬性配置來區分PC和移動頁面,避免樣式干擾。
然而,是我天真了,看網上各種postcss-px-to-viewport的exclude和include的配置,更換各個版本以及相似的更新版本,都不能完美做到相容移動端和PC端,我就放棄了移動pc放在一個項目中了,最終只能單獨的把移動頁面單獨摘出來成立一個單獨項目跑,坑爹啊。
-
表單密碼可見切換以及不讓輸入漢字空格
代碼實現:
<van-field :required="true" v-model="registerForm.password" :type="switchPassType ? 'text' : 'password'" name="password" label="登錄密碼" placeholder="請輸入登錄密碼" :right-icon="switchPassType ? 'eye' : 'closed-eye'" @click-right-icon="switchPassType = !switchPassType" :rules="rules.password" :update:model-value="registerForm.password=registerForm.password.replace(/[\u4e00-\u9fa5/\s+/]/ig,'')" /> 備註:密碼這塊雖然有些網上搜到的讓用vant 自帶的digit屬性讓只能輸入數字,但這個不符合產品需求,密碼應為數字、字母、特殊符號都可輸入。
使用van-field自帶的update:model-value方法進行漢字、空格校驗,親測有效。
2. 移動端頁面出現X軸滾動條問題
1) 在index.html文件中添加 <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,viewport-fit=cover"/> 2) 在公共樣式中修改html、body設置的樣式 html { overflow-y: scroll; }:root { overflow-y: auto; overflow-x: hidden; }
:root body { position: absolute; }
body { width: 100%; margin: 0; padding: 0; overflow: hidden; }
3.使用postcss-px-to-viewport做適配出現的問題
使用教程我就不贅述了,網上一大片,說點有用的 1)相容vant的375設置 在你的vue.config.js文件中添加如下代碼: css: { loaderOptions: { postcss: { postcssOptions: (loaderContext) => { return { plugins: [ ["autoprefixer"], // vant px轉vw。參坑:單獨寫在postcss.config.js中無法解析vant內部樣式 { "postcss-px-to-viewport": { unitToConvert: "px", viewportWidth: loaderContext.resourcePath.includes("vant") ? 375 : 750, // viewportWidth: 750, // 視窗的寬度,對應的是我們設計稿的寬度,一般是750 // viewportHeight: 1334, // 視窗的高度,根據750設備的寬度來指定,一般指定1334,也可以不配置 unitPrecision: 6, // 指定`px`轉換為視窗單位值的小數位數 propList: ["*"], viewportUnit: "vw", //指定需要轉換成的視窗單位,建議使用vw fontViewportUnit: "vw", selectorBlackList: [], // 如['.ignore'], 可以指定不轉換為視窗單位的類,可以自定義,可以無限添加,建議定義一至兩個通用的類名 minPixelValue: 1, // 小於或等於`1px`不轉換為視窗單位,你也可以設置為你想要的值 mediaQuery: true, // 允許在媒體查詢中轉換`px` exclude: [], landscape: false }, }, ], }; }, }, }, } 代碼目錄:
備註:其中的exclude屬性不知道樹我本人寫的有問題還是怎麼的,想用它處理views目錄下的特定目錄文件總是不生效,include就更別說了,各種版本、各種寫法都換過了沒啥nuan用。
4.檢測是否是移動端打開跳轉不同路由
1)路由處理
export const ISMOBILE = function () {
let flag = navigator.userAgent.match( /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i ); return flag; };5. DatePicker日期選擇器預設選中當前日期
在這塊有2個坑:
1)它的年份預設最小2013,不能像elementui的日期選擇器一樣自由選擇,所以,使用時你可以使用min-date屬性設置最小年月日。
2)預設選中當前年月日,
currentDate使用計算屬性獲取, 備註:月日不足2位要用0補齊,不然獲取到的當前年月日不對 /**獲取當前日期回填 */ const currentDate = computed(() => { const nowDate = myDate.toLocaleDateString().split("/"); if (nowDate[1].length < 2) { nowDate[1] = "0" + nowDate[1]; } if (nowDate[2].length < 2) { nowDate[1] = "0" + nowDate[2]; } return nowDate; });6. 表單校驗添加
1)一定要給van-form中添加ref屬性,在van-field中使用name作為校驗標識,使用rules屬性添加校驗規則。
備註:想要對一個欄位進行不同校驗以及不同提示,只能使用多條校驗規則。此處不能像使用elementUi中的callback返回提示語,只能使用message屬性寫死,操蛋啊
7.文件上傳預覽刪除
直接上代碼,很明瞭:
// 上傳圖片、上傳文件校驗大小和格式 const beforeRead = (file) => { const correctFormat = ["jpg", "jpeg", "png", "bmp"]; const isArray = Object.prototype.toString.call(file) === "[object Array]"; const isLimit50M = 1024 * 1024 * 6; // 是否大於50M if (isArray) { const sizes = file.map((item) => item.size); if (sizes.some((item) => item > isLimit50M)) { showNotify({ type: "warning", message: "大小不能超過6M" }); return false; } const types = file.map( ({ name }) => name.slice(name.lastIndexOf(".") + 1) // 尾碼 ); if (!types.every((item) => correctFormat.includes(item))) { showNotify({ type: "warning", message: "請上傳jpg/jpeg/png/bmp" }); return false; } } else { if (file.size > isLimit50M) { showNotify({ type: "warning", message: "大小不能超過6M" }); return false; } const type = file.name.slice(file.name.lastIndexOf(".") + 1); if (!correctFormat.includes(type)) { showNotify({ type: "warning", message: "請上傳jpg/jpeg/png/bmp" }); return false; } } return true; };// 文件上傳 const fileUpload = (data, key, id, file) => { fileUploadApi(data) .then((res) => { if (res.status === 1) { res.data.key = new Date().getTime(); res.data.url = res.data.attachPreviewUrl; res.data.percent = 100; res.data.status = "success"; res.data.name = res.data.attachSrcName; res.data.uid = id; registerForm[key] = []; registerForm[key].push(res.data); file.status = "success"; showNotify({ type: "success", message: "上傳成功" }); return true; } else { file.status = "failed"; showNotify({ type: "danger", message: "上傳失敗,請重新上傳" }); return false; } }) .catch((err) => { showNotify({ type: "danger", message: err.message }); return false; }); }; /**文件上傳動作 */ const myBeforeRead = (file, field) => { if (beforeRead(file)) { file.status = "uploading"; file.message = "上傳中..."; uploadData.file = file; uploadData.field = field; const form = new FormData(); const keys = Object.keys(uploadData); keys.forEach((key) => { form.append(key, uploadData[key]); }); // 後臺介面 if (fileUpload(form, uploadData.field, file.lastModified, file)) { return true; } else { return false; } } else { return false; } }; /**文件刪除動作 */ const delImg = (file, field) => { registerForm[field] = []; proxy.$refs.registerFormRef.validate(field); };