前端技巧总结---持续更新
易遺漏事件總結(jié)
關(guān)閉/保存后
-
重置
- 一些變量、表單
-
考慮業(yè)務(wù)流程
-
加載數(shù)據(jù)提示
移動(dòng)端技巧總結(jié)
阿里圖庫
在原有的基礎(chǔ)上加新圖標(biāo)
該代碼替換掉原有的 iconfont.css
?src 請(qǐng)求頭要加https,要不然移動(dòng)端會(huì)不顯示阿里圖標(biāo)
onBackPress 返回上一級(jí)
onBackPress() {// ...自定義操作---提示(是否確認(rèn)退出) if (this.ruleForm.Id) {uni.navigateTo({// 跳轉(zhuǎn)到平常頁面url: '/pages/business/B_WayBill/B_WayBill'})} else {// 跳轉(zhuǎn)到 tabbar 頁面uni.switchTab({url: '/pages/work/work'})}return true }實(shí)現(xiàn)這種提示:
<!--關(guān)閉按鈕顯示與否--><u-modal :closeOnClickOverlay="true" @close="show = false" @cancel="show = false" cancelText="繼續(xù)編輯"confirmText="下次再編輯" :show="show" @confirm="close" :showCancelButton="true" title="還差一點(diǎn)就添加成功了"></u-modal> // 點(diǎn)擊左上角返回按鈕觸發(fā) onBackPress() {this.show = truereturn true }close(){uni.navigateTo(...) }?close事件不要用 navigateBack 會(huì)進(jìn)入死循環(huán)
?路徑傳參
uni.navigateTo({url: `/pages/business/B_WayBill_Add/components/cargoMessage?rowData=${JSON.stringify(this.rowData)}&cargoData=${JSON.stringify(row)}` });?如果傳遞的參數(shù)是對(duì)象,需要用 JSON.stringify 轉(zhuǎn)成字符串,后面接受數(shù)據(jù)再用 JSON.parse 轉(zhuǎn)成 object
條件編輯
- // #ifdef H5 // #endif// #ifdef APP-PLUS<!-- #ifndef MP-WEIXIN --> ?除了這種之外<!-- #ifdef MP-WEIXIN -->
頁面下拉刷新事件
async onPullDownRefresh() {this.getData()// 停止刷新uni.stopPullDownRefresh() }// 同時(shí)要在 pages 里面設(shè)置返回頂部
<!-- 返回頂部的按鈕組件 --> <u-back-top class="u-back-top" :iconStyle="{color:'#fff'}" icon="arrow-up" :scroll-top="scrollTop"></u-back-top>// 監(jiān)聽返回頂部按鈕的距離 onPageScroll(e) {this.scrollTop = e.scrollTop; }頁面重置到頂部
uni.pageScrollTo({scrollTop: 0,duration: 0 });搜索定位
uni.pageScrollTo({scrollTop:dom元素(vue里面的ref).offsetTop, })圖片預(yù)覽
uni.previewImage({current: "",urls: [e], })頁面跳轉(zhuǎn)
// 頁面會(huì)刷新觸發(fā)onLoad(有表單組件的話需要存起來 uni.navigateTo() ?url要帶'/',eg:'/pages/...'// 頁面不會(huì)刷新(有表單組件 uni.navigateBack()uniapp開發(fā)
獲取this.$refs為空對(duì)象或者為undefined
解決方法
非H5端只能用于獲取自定義組件,不能用于獲取內(nèi)置組件實(shí)例(如:view、text)
ref組件使用了條件渲染,即v-if、v-show,這些DOM節(jié)點(diǎn)在mounted無法被訪問到
使用了 v-for 循環(huán)動(dòng)態(tài)綁定ref(大部分時(shí)請(qǐng)求后端數(shù)據(jù)動(dòng)態(tài)渲染DOM),this.$ref[name]獲取的是數(shù)組
- 用法應(yīng)該為 dom[x].xx
非H5端只能用于獲取自定義組件,不能用于獲取內(nèi)置組件實(shí)例(如:view、text) $el只支持H5端
const query = uni.createSelectorQuery().in(this)query.select(`#${res.Data.BillInfo.BillNo}`).boundingClientRect(data => {console.log(data) // 返回節(jié)點(diǎn)的相對(duì)坐標(biāo)信息top、bottom等 //查詢當(dāng)前屏幕的滾動(dòng)位置等信息uni.createSelectorQuery().selectViewport().scrollOffset(result => {// result.scrollTopuni.pageScrollTo({scrollTop: Math.abs(data.top) - 300,duration: 100});}).exec();}).exec();熟悉業(yè)務(wù)需求
- 完成狀態(tài)下沒有完成中的操作(狀態(tài)
- 完成業(yè)務(wù)后重置刷新數(shù)據(jù)
- 初始賦值
可以使用JavaScript的reduce()方法來合并具有相同屬性和值的對(duì)象
const mergedTaleData = data.tableData.reduce((acc, curr) => {const existingObj = acc.find(obj => obj.PickBill_Id == curr.PickBill_Id && obj.FeeName == curr.FeeName && obj.Currency == curr.Currency);console.log(existingObj, acc, curr);if (existingObj) {existingObj.AccTotal = xeUtils.add(existingObj.AccTotal, curr.AccTotal);existingObj.Acc = xeUtils.add(existingObj.Acc, curr.Acc);} else {acc.push({ ...curr, AccTotal: curr.AccTotal, Acc: curr.Acc });}return acc;}, []);響應(yīng)式數(shù)組置空
- resultData.value.length = 0
有時(shí)候 disabled 的樣式安卓端與ios端可能不一樣
/deep/ .uni-input-input:disabled { // 安卓color: #666; }/deep/ .is-disabled { // ioscolor: #666; }異步操作放在actions中,actions通過commit調(diào)用mutations中方法操作state
地址轉(zhuǎn)經(jīng)緯度
uni.request({url: 'https://restapi.amap.com/v3/geocode/geo?parameters',method: 'GET',data: {key: '', //高德地圖keyaddress: '廣東省湛江市' // 詳細(xì)地址},success: (res) => {let lo = res.data.geocodes[0].location.split(',')[0]let la = res.data.geocodes[0].location.split(',')[1]console.log(lo,la);navigaToShop({latitude: lo,longitude: la,stationname: res.data.geocodes[0].formatted_address})},fail: (err) => {this.$toast(err)} })APP(IOS Android )轉(zhuǎn)到高德地圖、百度地圖、騰訊地圖
// getMap.jsexport function getCurLocation() {uni.getLocation({geocode: true,type: 'gcj02',success: (res) => {}})}//打開第三方地圖export function toMapAPP(latitude, longitude, address) {let url = ''if (plus.os.name == "Android") { //判斷是安卓端let url = "";plus.nativeUI.actionSheet({ //選擇菜單title: "選擇地圖應(yīng)用",cancel: "取消",buttons: [{title: "騰訊地圖"}, {title: "百度地圖"}, {title: "高德地圖"}]}, function(e) {switch (e.index) {//下面是拼接url,不同系統(tǒng)以及不同地圖都有不同的拼接字段case 1://注意referer=xxx的xxx替換成你在騰訊地圖開發(fā)平臺(tái)申請(qǐng)的keyurl =`qqmap://map/routeplan?type=drive&from=我的位置&fromcoord=CurrentLocation&to=${address}&tocoord=${latitude},${longitude}&referer=`;break;case 2:url ="baidumap://map/direction?origin=我的位置" +"&destination=name:" + address +"|latlng:" + latitude + "," + longitude +"&coord_type=gcj02&mode=driving&src=andr.baidu.openAPIdemo"break;case 3:url =`amapuri://route/plan/?did=&dlat=${latitude}&dlon=${longitude}&dname=${address}&dev=0&t=0`break;default:break;}if (url != "") {url = encodeURI(url);//plus.runtime.openURL(url,function(e){})調(diào)起手機(jī)APP應(yīng)用plus.runtime.openURL(url, function(e) {plus.nativeUI.alert("本機(jī)未安裝指定的地圖應(yīng)用");});}})} else {// iOS上獲取本機(jī)是否安裝了百度高德地圖,需要在manifest里配置// 在manifest.json文件app-plus->distribute->apple->urlschemewhitelist節(jié)點(diǎn)下添加//(如urlschemewhitelist:["iosamap","baidumap"]) plus.nativeUI.actionSheet({title: "選擇地圖應(yīng)用",cancel: "取消",buttons: [{title: "高德地圖"}, {title: "百度地圖"}, {title: "騰訊地圖"}]}, function(e) {switch (e.index) {case 1:url =`iosamap://path?sourceApplication=applicationName&did=&dlat=${latitude}&dlon=${longitude}&dname=${address}&dev=0&t=0`;break;case 2:url = "baidumap://map/direction?origin=我的位置" +"&destination=name:" + address +"|latlng:" + latitude + "," + longitude +"&coord_type=gcj02&mode=driving&src=ios.baidu.openAPIdemo";break;case 3:url =`qqmap://map/routeplan?type=drive&from=我的位置&fromcoord=CurrentLocation&to=${address}&tocoord=${latitude},${longitude}&referer=`;break;default:break;}if (url != "") {url = encodeURI(url);plus.runtime.openURL(url, function(e) {plus.nativeUI.alert("本機(jī)未安裝指定的地圖應(yīng)用");});}})}}uniapp某個(gè)容器滾動(dòng)到底部事件
<scroll-view v-if="actionSheetCurrentItem.remote" :scroll-top="scrollTop" scroll-y="true"@scrolltolower="scrolltolower" style="height: 300px" @scroll="scroll"></scroll-view>scrollTop: 0, old: {scrollTop: 0 }scroll: function(e) {this.old.scrollTop = e.detail.scrollTop }// 置頂 // 解決view層不同步的問題this.scrollTop = this.old.scrollTopthis.$nextTick(function() {this.scrollTop = 0});置頂頭部部分
position: fixed; background-color: skyblue; height: 50px; line-height: 50px; top: 44px; z-index: 999; width: 100%; // app平臺(tái)的代碼 // #ifdef APP-PLUS position: fixed; top: 0px; z-index: 9999;點(diǎn)擊電話調(diào)起撥打功能
<a :href="'tel:' + item.VehiclenoCarManTel">{{item.VehiclenoCarManTel}}</a>PDA(iData)
- 注意開啟以及結(jié)束的時(shí)機(jī)
- 開啟新一個(gè)要結(jié)束掉上一個(gè)
- ?使用插件如果要用到 this 要合理的使用箭頭函數(shù)
語音播報(bào)
const TTSSpeech = uni.requireNativePlugin("MT-TTS-Speech");TTSSpeech.speak({text})關(guān)于封裝組件的技巧
-
分析需求
- 把頁面中可以復(fù)用的 ?結(jié)構(gòu)、樣式以及功能? 單獨(dú)抽離成一個(gè)
-
具體步驟
- Vue.component (全局)components: {}(局部) 注冊(cè)組件
- 子:props 接收數(shù)據(jù) emits觸發(fā)父的自定義事件 父::傳輸數(shù)據(jù) @自定義事件
- 組件傳入模板 則定義為插槽 slot
- 數(shù)據(jù)或者方法之類的如果需要被調(diào)用,記得暴露出來
-
一個(gè)強(qiáng)大的公用組件包含的文件可分為:
- hooks.js
- 公共的方法、樣式等
- index.vue
- 組件主要邏輯
- porps.js
- 接受傳過來的數(shù)據(jù)
- linkColumn.vue
- 子組件.vue
- hooks.js
記得使用數(shù)組方法
-
some
-
every
-
filter
-
find
-
reduce
-
map
APP上架到iosStore的注意事項(xiàng)
不用蘋果電腦的Xcode↓↓↓
ipa上傳工具
- app Store 的圖標(biāo)不能是透明的,而且圖標(biāo)不能包含圓角
APP隱私聲明示例
歡迎您使用本軟件(以下簡(jiǎn)稱“本服務(wù)”),本軟件是由xx有限公司(以下簡(jiǎn)稱“本公司”)向員工提供的工作軟件。為保證您的權(quán)益,便于更好地使用本軟件及相應(yīng)的配套服務(wù),請(qǐng)您務(wù)必在注冊(cè)前認(rèn)真閱讀本協(xié)議,若您閱讀并接受本協(xié)議,使用本軟件提供的產(chǎn)品和服務(wù),即視為您受本協(xié)議的約束,若您不同意本協(xié)議,請(qǐng)勿使用本網(wǎng)站任何產(chǎn)品和服務(wù)。一、服務(wù)內(nèi)容本軟件運(yùn)用自己的系統(tǒng)通過互聯(lián)網(wǎng)絡(luò)為用戶提供軟件交易、工程師服務(wù)等服務(wù)。用戶使用本服務(wù)需要下載本軟件客戶端軟件,同時(shí),用戶必須:1、自行配備上網(wǎng)所需設(shè)備,包括個(gè)人電腦、調(diào)制解調(diào)器或其他必備上網(wǎng)裝置。2、自行負(fù)擔(dān)個(gè)人上網(wǎng)所支付的與此服務(wù)有關(guān)的電話費(fèi)用、網(wǎng)絡(luò)費(fèi)用。3、基于本軟件所提供的服務(wù)的重要性,用戶應(yīng)同意:1)提供詳盡、準(zhǔn)確的個(gè)人資料。2)不斷更新注冊(cè)資料,符合及時(shí)、詳盡、準(zhǔn)確的要求,如果您提供的注冊(cè)資料不合法、不真實(shí)的,需自行承擔(dān)由此引起的責(zé)任及后果,本公司保留終止您使用本軟件各項(xiàng)服務(wù)的權(quán)利。4、為防止他人冒用您的身份注冊(cè)、使用本服務(wù),企鵝外匯可能會(huì)給您的手機(jī)發(fā)送短信進(jìn)行驗(yàn)證,由此產(chǎn)生的短信費(fèi)用由本公司支付,您不需支付任何費(fèi)用。二、服務(wù)的提供、修改及終止1、您保證在您同意接受本協(xié)議并注冊(cè)成為本軟件用戶時(shí),您已經(jīng)年滿18周歲,您是具備完全民事權(quán)利能力和完全民事行為能力的自然人。2、在接受本公司各項(xiàng)服務(wù)的同時(shí),您同意接受本公司提供的各類信息服務(wù),并在此授權(quán)本公司可以向您電子郵件、手機(jī)等發(fā)送商業(yè)信息。3、您有權(quán)選擇不接受本公司提供的各類信息服務(wù),并進(jìn)入本軟件相關(guān)頁面進(jìn)行更改。4、本公司可以提前3天通知,單方終止本協(xié)議。5、本軟件有權(quán)在必要時(shí)修改服務(wù)條款,若您對(duì)本協(xié)議的修改有異議,您可以停止使用本軟件的網(wǎng)絡(luò)服務(wù),在此情況下,本軟件沒有義務(wù)傳送任何未處理的信息或未完成的服務(wù)給您或任何無直接關(guān)聯(lián)的第三方。三、用戶隱私制度1、本公司將會(huì)采取合法、合理的措施保護(hù)用戶的個(gè)人信息,非經(jīng)法定原因或用戶事先許可,本公司不會(huì)向任何第三方透露您的密碼、姓名、手機(jī)號(hào)碼等非公開信息。以下情況除外:1)用戶授權(quán)本軟件透露這些信息。2)相關(guān)的法律法規(guī)或監(jiān)管機(jī)構(gòu)、司法機(jī)構(gòu)要求本軟件提供您的個(gè)人資料;國家司法機(jī)關(guān)符合法律規(guī)定并經(jīng)法定程序的檢查及其他操作。3)任何第三方盜用、冒用或未經(jīng)許可擅自披露、使用或?qū)ν夤_您的個(gè)人隱私資料。4)由您要求網(wǎng)站提供特定服務(wù)時(shí),需要把您的姓名和地址提供給第三方的。5)您在使用本服務(wù)、參加網(wǎng)站活動(dòng)或訪問網(wǎng)站網(wǎng)頁時(shí),自動(dòng)接收并記錄的瀏覽器端或手機(jī)客戶端數(shù)據(jù),包括但不限于IP地址、網(wǎng)站Cookie中的資料及您要求取用的網(wǎng)頁記錄。6)本軟件從商業(yè)伙伴處合法獲取的個(gè)人信息。 7)我們的產(chǎn)品基于DCloud uni-app(5+App/Wap2App)開發(fā),應(yīng)用運(yùn)行期間需要收集您的設(shè)備唯一識(shí)別碼(IMEI/androidID/DEVICE_ID/IDFA、SIM 卡 IMSI信息、OAID)以提供統(tǒng)計(jì)分析服務(wù),并通過應(yīng)用啟動(dòng)數(shù)據(jù)及異常錯(cuò)誤日志分析改進(jìn)性能和用戶體驗(yàn),為用戶提供更好的服務(wù)。2、在適合的情況下,并在您同意的前提下,我們會(huì)利用您的信息來聯(lián)絡(luò)您,為您發(fā)送信息。3、您應(yīng)當(dāng)妥善保管您的設(shè)備和密碼及身份信息,對(duì)于因密碼泄露、身份信息泄露、設(shè)備丟失所致的損失,由您自行承擔(dān)。四、用戶行為規(guī)范除非法律允許或本公司書面許可,您使用本軟件過程中不得從事下列行為:1、刪除本軟件及其副本上關(guān)于著作權(quán)的信息。2、對(duì)本軟件進(jìn)行反向工程、反向匯編、反向編譯,或者以其他方式嘗試發(fā)現(xiàn)本軟件的源代碼。3、對(duì)本公司擁有知識(shí)產(chǎn)權(quán)的內(nèi)容進(jìn)行使用、出租、出借、復(fù)制、修改、鏈接、轉(zhuǎn)載、匯編、發(fā)表、出版、建立鏡像站點(diǎn)等。4、對(duì)本軟件或者本軟件運(yùn)行過程中釋放到任何終端內(nèi)存中的數(shù)據(jù)、軟件運(yùn)行過程中客戶端與服務(wù)器端的交互數(shù)據(jù),以及本軟件運(yùn)行所必需的系統(tǒng)數(shù)據(jù),進(jìn)行復(fù)制、修改、增加、刪除、掛接運(yùn)行或創(chuàng)作任何衍生作品,形式包括但不限于使用插件、外掛或非本公司經(jīng)授權(quán)的第三方工具/服務(wù)接入本軟件和相關(guān)系統(tǒng)。5、通過修改或偽造軟件運(yùn)行中的指令、數(shù)據(jù),增加、刪減、變動(dòng)軟件的功能或運(yùn)行效果,或者將用于上述用途的軟件、方法進(jìn)行運(yùn)營或向公眾傳播,無論這些行為是否為商業(yè)目的。6、通過修改或偽造軟件運(yùn)行中的指令、數(shù)據(jù),增加、刪減、變動(dòng)軟件的功能或運(yùn)行效果,或者將用于上述用途的軟件、方法進(jìn)行運(yùn)營或向公眾傳播,無論這些行為是否為商業(yè)目的。7、自行或者授權(quán)他人、第三方軟件對(duì)本軟件及其組件、模塊、數(shù)據(jù)進(jìn)行干擾。8、其他未經(jīng)本公司明示授權(quán)的行為。 五、適用法律和管轄權(quán)1、企鵝外匯注冊(cè)所在地法律、法規(guī)應(yīng)規(guī)范本協(xié)議以及本協(xié)議各方之間引起的爭(zhēng)議,除非存在法律指定適用其他管轄法律。2、在合約一方尋求實(shí)現(xiàn)本協(xié)議下的權(quán)利,或?qū)で笮姹緟f(xié)議下的任何權(quán)利或義務(wù)的任何民事訴訟或其他訴訟過程中,各合約方應(yīng)承擔(dān)其代理律師的費(fèi)用和支出。3、本協(xié)議的解釋語言應(yīng)為中文。4、本公司可能通過多種語言將本協(xié)議或任何其他文件、信息和消息提供給合作方。本協(xié)議規(guī)定,合作方應(yīng)當(dāng)承認(rèn)及確認(rèn)本公司工作語言為中文。如果任何文件、信息和消息的非中文表述和中文表述之間出現(xiàn)矛盾和不一致的情況下,雙方將以中文文件、信息和消息為標(biāo)準(zhǔn)。Guideline 2.1 - Information Needed
Dear Review team: After receiving your reason for rejection back, we carefully verified the interior of the application and found nothing wrong with what you said. In order to avoid unnecessary misunderstanding, we specially provide the relevant qualification certificate, and provide the following instructions: 1. Is your app limited to users who belong to the same company? This may include users of company partners, employees, and contractors. No, our app can serve employees and customers of different logistics companies. 2. Is your app designed for a limited or specific group of companies? Yes, our app is specifically for international logistics companies. 3. What features (if any) in the application are intended for public use? No. 4. Determine which countries or territories you plan to release your application in?The app plans to roll out China to China. 5. How do users get an account? We also have a back office system where the administrator gives the user account. 6. Is there paid content in the app? For example, does the user pay to open an account or use certain features in the app? The app doesn't have a paid feature. Users don't have to pay for any features, and all features are free to try. 7. Who pays for premium content and how do users access it? The App has no payment function, and users can access all content by logging into the app after obtaining an account.Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
詳細(xì)介紹申請(qǐng)這些權(quán)限的用處
PC端(Vue)技巧總結(jié)
element
多試試插槽,實(shí)現(xiàn)個(gè)性化樣式
<template #title><el-tag effect="dark" size="large" style="margin-right: 10px;">主單號(hào)</el-tag> </template>loading的多種使用方式
-
默認(rèn)loading
- v-loading 綁定布爾值
-
自定義loading
- v-loading="loading" element-loading-text="拼命加載中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)"
-
整頁加載
分割組件 splitpanes
import { Splitpanes, Pane } from 'splitpanes'; import 'splitpanes/dist/splitpanes.css';<splitpanes style="height: 100%"><pane :size="40" v-if="!rowData"></pane> </splitpanes>vuex 的使用
const state = {lang:getLang(), }const mutations = {SET_LANG(state, lang){state.lang = langsetLang(lang)} }const actions = {changeLang({commit}, lang){commit('SET_LANG', lang)} }export default {namespaced: true,state,mutations,actions, } import { mapState } from 'vuex' import store from '@/store/index.js'computed: {...mapState("addOrderCargo", ["sendMessage", "recieveMessage", "productOptions", "inventoryData", "ruleForm"]) }store.getters.inventoryDatastore.commit('addOrderCargo/setproductOptions', res.data)自定義指令
指令鉤子
const myDirective = {// 在綁定元素的 attribute 前// 或事件監(jiān)聽器應(yīng)用前調(diào)用created(el, binding, vnode, prevVnode) {// 下面會(huì)介紹各個(gè)參數(shù)的細(xì)節(jié)},// 在元素被插入到 DOM 前調(diào)用beforeMount(el, binding, vnode, prevVnode) {},// 在綁定元素的父組件// 及他自己的所有子節(jié)點(diǎn)都掛載完成后調(diào)用mounted(el, binding, vnode, prevVnode) {},// 綁定元素的父組件更新前調(diào)用beforeUpdate(el, binding, vnode, prevVnode) {},// 在綁定元素的父組件// 及他自己的所有子節(jié)點(diǎn)都更新后調(diào)用updated(el, binding, vnode, prevVnode) {},// 綁定元素的父組件卸載前調(diào)用beforeUnmount(el, binding, vnode, prevVnode) {},// 綁定元素的父組件卸載后調(diào)用unmounted(el, binding, vnode, prevVnode) {} }鉤子參數(shù)
el:指令綁定到的元素。這可以用于直接操作 DOM。binding:一個(gè)對(duì)象,包含以下屬性。value:傳遞給指令的值。例如在 v-my-directive="1 + 1" 中,值是 2。 oldValue:之前的值,僅在 beforeUpdate 和 updated 中可用。無論值是否更改,它都可用。 arg:傳遞給指令的參數(shù) (如果有的話)。例如在 v-my-directive:foo 中,參數(shù)是 "foo"。 modifiers:一個(gè)包含修飾符的對(duì)象 (如果有的話)。例如在 v-my-directive.foo.bar 中,修飾符對(duì)象是 { foo: true, bar: true }。 instance:使用該指令的組件實(shí)例。 dir:指令的定義對(duì)象。 vnode:代表綁定元素的底層 VNode。prevNode:之前的渲染中代表指令所綁定元素的 VNode。僅在 beforeUpdate 和 updated 鉤子中可用。使用示例
// VTrim.js ----局部 /***全局去掉輸入框前后空格指令*/ function getInput(el){let inputEleif(el.tagName !== 'INPUT'){inputEle = el.querySelector('input')}else{inputEle = el}return inputEle }function dispathEvent(el,type){const evt = document.creatEvent('HTMLEvents')evt.initEvent(type, true, true)el.dispatchEvent(evt) }const trimDirective = {mounted(el){const inputEle = getInput(el)const handler = function (event) {const newVal = event.target.value.trim()if (event.target.value !== newVal) {event.target.value = newValdispatchEvent(inputEle, 'input')}}// 回車后過濾空格(因?yàn)檩斎肟蚩梢曰剀囌{(diào)接口查詢,所以這時(shí)候單純的失去焦點(diǎn)過濾不起作用,要對(duì)回車鍵單獨(dú)做一下處理)const keydown = function (event) {if (event.keyCode === 13) {const newVal = event.target.value.trim()if (event.target.value !== newVal) {event.target.value = newValdispatchEvent(inputEle, 'input')}}}el.inputEle = inputEleel._blurHandler = handlerel._keyHandler = keydowninputEle.addEventListener('blur', handler)inputEle.addEventListener('keydown', keydown)},unmounted(el) {const {inputEle} = elinputEle.removeEventListener('blur', el._blurHandler)inputEle.removeEventListener('keydown', el._keyHandler)} }export default trimDirective;// 使用 import Trim from "@/directives/VTrim"; // directives節(jié)點(diǎn)聲明 directives:{Trim},// tempalte中使用 <el-input v-trim></el-input> // 全局 const getInput = elm =>elm instanceof HTMLInputElement ? elm : elm.querySelector('input') app.directive('focus',{mounted(el,{arg}){if(arg) el.focus?.()else getInput(el)?.focus()} })后臺(tái)管理版本更新
import axios from 'axios'export const isNewVersion = () => {// 開發(fā)環(huán)境不做判斷if (process.env.NODE_ENV === 'development') return// 線上環(huán)境判斷版本號(hào)let url = `//${window.location.host}/version.json?t=${new Date().getTime()}`axios.get(url).then(res => {if (res.status === 200) {let vueVersion = res.data.version || '1.0.0'let localVueVersion = localStorage.getItem('vueVersion')localStorage.setItem('vueVersion', vueVersion)if (localVueVersion && localVueVersion != vueVersion) {alert('檢測(cè)到新版本,請(qǐng)點(diǎn)擊確認(rèn)刷新頁面,加載資源需要一些時(shí)間,請(qǐng)稍等!')window.location.reload(true)return}}}) }export default {isNewVersion }Vue2
Vue2 data or props 用到另外一個(gè)數(shù)值,記得函數(shù)不能用箭頭函數(shù),會(huì)把this丟失掉
vue2 引入組件
import yhCascader from '@/components/YhCascader'components:{}// 全局 main.js import yhUpload from '@/components/yh-upload/yh-upload'watch
"sendMessage.MailingType": {handler(oldVal, newVal) {this.getSendAddress()},deep: true, // 深度監(jiān)聽immediate: true // 第一次改變就執(zhí)行}computed
計(jì)算后屬性必須渲染后,綁定的方法才會(huì)生效這里指就是定義后的變量名在上面html中顯示
vue2一個(gè)對(duì)象中的一個(gè)值是一個(gè)計(jì)算屬性
怎么搞?—只有計(jì)算屬性依賴項(xiàng)變化才回觸發(fā)
vue3
defineComponent
- vue3中,新增了 defineComponent ,它并沒有實(shí)現(xiàn)任何的邏輯,只是把接收的 Object 直接返回,它的存在是完全讓傳入的整個(gè)對(duì)象獲得對(duì)應(yīng)的類型,可以獲得自動(dòng)提示。
計(jì)算屬性(一個(gè)頁面可以使用多個(gè)computed和多個(gè) watch)
- data中的一個(gè)值如果依賴另一個(gè)值記得寫成計(jì)算屬性,不然不會(huì)同步
組合式API
// 1 export dedfault{setup(){...// 要 return 數(shù)據(jù)、函數(shù) 出去return {...}} }// 2 script setup 語法糖 不需要在setup函數(shù)里面寫代碼了,不需要 return,vue3 自動(dòng)返回 <script setup></script>引入組件
import yhCascader from '@/components/YhCascaderexport default {components: {yhCascader} }總–總結(jié)
判斷數(shù)據(jù)類型
const keyType = data => {let type = Object.prototype.toString.call(data);if (type === '[object String]') {type = 'String';} else if (type === '[object Number]') {type = 'Number';} else if (type === '[object Null]') {type = 'Null';} else if (type === '[object Boolean]') {type = 'Boolean';} else if (type === '[object Array]') {type = 'Array';} else if (type === '[object Object]') {type = 'Object';} else {type = '未進(jìn)行判斷的類型:' + type;}return type; };對(duì)象包裹對(duì)象轉(zhuǎn)換為數(shù)組
for in + pushfilter
賦值數(shù)據(jù)
const data = res.data || []封裝
將一些通用的參數(shù)和函數(shù)抽離出來,封裝成一個(gè)通用的 hook
eg:定義列表頁面的分頁數(shù)據(jù)
export const pageHook = () => {return {sort: '',order: 'desc',Foots: '',total: 0,} }對(duì)象
深拷貝
JSON.parse(JSON.Stringfy())有key字段,但還需要value字段
- 直接使用 . 加一個(gè)名稱屬性給 Object
不同屬性類型共享同一個(gè) object
對(duì)象賦值
for (let key in ruleForm) {ruleForm[key] = value[key]}callBack 合理使用
封裝組件需要注意的點(diǎn)
-
顯示與否
-
傳遞數(shù)據(jù)另給一個(gè) js 文件存放
-
import propsData from './props'
- // props.js export default {leftColumns: {type: Array,default: () => []}, }
-
-
個(gè)性化–合理利用插槽
- <slot name="rightTop"></slot>
-
組件間傳遞數(shù)據(jù)
- props emits
-
數(shù)據(jù)更新問題
-
$nextTick
-
定時(shí)器
- setTimeout(()=> {emits('changeAfter')},200)
-
-
vue3 在 data 中 使用 compute
- list:computed(()=>{...})
-
使用三段式
- let activeData = isAll ? getLeftData() : leftTableRef.value.getSelected():type="isShowLeftList ? 'info' : 'success'"
-
巧用 v-model
-
子
- props:{value: {type: Array,default: () => [],} }
-
父
- this.$emits('input',data)
-
使用組件 用 v-model
-
v-model 的值就能關(guān)聯(lián) 父里面的 data值了
-
?v-if 會(huì)影響到 ref 的獲取
請(qǐng)求接口參數(shù)
-
拼接參數(shù)
- ?a=$&
-
formData
?async返回值都是 promise對(duì)象
解決:
-
分開
-
如果是 promise 的話,用 resolve返回
?善于利用 uniapp 的 API + Promise
-
代碼式書寫,解決先后執(zhí)行問題
請(qǐng)求接口的是否加載可以加在config里面
-
用 axios 的請(qǐng)求攔截器接收
-
請(qǐng)求攔截器接收之后可以再響應(yīng)攔截器中拿到并判斷關(guān)閉
實(shí)現(xiàn)左右滑動(dòng)
.insure {display: flex;height: 520px;.left {width: 40%;// overflow: auto;.header {}}.right {flex: 1;// overflow: auto;} }-
elementUI有個(gè)滾動(dòng)條樣式
循環(huán)一般用來讀取數(shù)據(jù),而不要改變響應(yīng)式數(shù)據(jù)
根據(jù)這個(gè)思路,可以把methods或者computed計(jì)算完的數(shù)據(jù)放置于數(shù)組中,再在響應(yīng)式內(nèi)直接讀取數(shù)組元素
APP(andriod,ios)熱更新
代碼:https://blog.csdn.net/itopit/article/details/124620871
借鑒:https://blog.csdn.net/m_xiaozhilei/article/details/126485684
打包的wgt版本要與后端記錄的一樣,線下打包的可以搞成第一點(diǎn)版本的去測(cè)試
// APP.vue onLauch(){//檢查更新// #ifdef APP-PLUSplus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {uni.setStorageSync("curversion", widgetInfo.version);let curversion = widgetInfo.version;console.log("當(dāng)前版本", curversion);hotupdate.getAppByVersion(curversion, true);});// #endif }// hotupdate.js import http from './http.js'function update(fileName) {let downURL = fileName;console.log('下載地址', downURL);//后臺(tái)顯示進(jìn)度條let dtask = plus.downloader.createDownload(downURL, {},function(d, status) {//下載完成install(d, status);// uni.showModal({// title: "版本更新",// content: "新版本已經(jīng)準(zhǔn)備好,是否更新應(yīng)用?",// success: (res) => {// if (res.confirm) {// install(d, status);// }// },// });});start(dtask); };function start(dtask) {try {dtask.start(); //開啟下載任務(wù)let prg = 0;let showLoading = plus.nativeUI.showWaiting("正在下載");dtask.addEventListener("statechanged", function(task, status) {switch (task.state) {case 1:showLoading.setTitle("正在下載");break;case 2:showLoading.setTitle("已連接到服務(wù)器");break;case 3:prg = parseInt((parseFloat(task.downloadedSize) /parseFloat(task.totalSize)) *100);showLoading.setTitle(" 正在下載" + prg + "% ");break;case 4:plus.nativeUI.closeWaiting();break;}});} catch (err) {plus.nativeUI.closeWaiting();uni.showToast({title: "更新失敗-03",mask: false,duration: 1500,});} };function install(d, status) {//下載完成if (status === 200) {plus.runtime.install(d.filename, {force: false}, function() {plus.nativeUI.closeWaiting();plus.runtime.restart();// plus.nativeUI.alert("應(yīng)用資源更新完成!是否重啟應(yīng)用!", function() {// plus.runtime.restart();// });}, function(e) {plus.nativeUI.closeWaiting();console.log("安裝wgt文件失敗[" + e.code + "]:" + e.message);plus.nativeUI.alert("安裝wgt文件失敗[" + e.code + "]:" + e.message);});} else {uni.showToast({title: "下載失敗",mask: false,duration: 1500,});} };function close(version) {try {console.log('保存要跳過的版本', version)uni.setStorageSync('skip_version', version);} catch (e) {// error} };function signOut() {// #ifdef APP-PLUSplus.runtime.quit();// #endif }export default {getAppByVersion(curversion, back) {console.log("came in");let params = {};if (uni.getSystemInfoSync().platform == "ios") {params = {app: "kdapp",type: "ios",appversion: curversion,};} else {params = {app: "kdapp",type: "android",appversion: curversion,};}// console.log(curversion);http.post(`/api/B_App_Ver_Record/GetNewAppVersion?VersionName=${curversion}`).then((res) => {console.log('version res');console.log(res);if (res.status && res.data[0]) {let result = res.data[0];if (back) {try {const value = uni.getStorageSync('skip_version');console.log('是否跳過當(dāng)前版本', value, result.versionName)if (value && value === result.versionName) {return;}} catch (e) {}}if (result.versionName != curversion) {// console.log('有新版本要更新', result);// console.log('新版本', result.versionName);// console.log('目前版本', curversion);result.back = back;// if (uni.getSystemInfoSync().platform != "ios") {plus.nativeUI.confirm(result.verDescription || "系統(tǒng)提示", function(e) {if (e.index == 1) {console.log('update', result.filePath);update(http.fileAddress + result.filePath);} else if (result.forceUpdate == 1) {signOut();} else if (result.forceUpdate == 0) {close(result.versionName);}}, {"title": "版本更新","buttons": [result.forceUpdate == 1 ? "退出應(yīng)用" : "暫不更新", "立即更新"]});// } else {// uni.showModal({// title: "版本更新",// content: "請(qǐng)點(diǎn)擊按鈕復(fù)制鏈接,粘貼到Safari瀏覽器打開,下載最新版本",// confirmText: "點(diǎn)擊復(fù)制",// showCancel: false,// success: () => {// uni.setClipboardData({// data: http.fileAddress + result.filePath,// success: () => {// uni.showToast({// title: "復(fù)制鏈接成功,請(qǐng)粘貼到Safari瀏覽器打開"// })// }// })// }// });// }} else if (!back) {//plus.nativeUI.alert("當(dāng)前已是最新版本!");}} else if (!res.status) console.log('error');uni.showToast({title: res.msg,icon: 'none', //如果要純文本,不要icon,將值設(shè)為'none'duration: 3000 //持續(xù)時(shí)間為 2秒});} else if (!back) {//plus.nativeUI.alert("當(dāng)前已是最新版本!");}})} }高亮與不高亮基本大小要一樣才不會(huì)變來邊去
請(qǐng)求參數(shù)如果沒有就不添加:
let params = {}if (this.keyword2) {params["billNo"]=this.keyword2}if (this.startTime2 && this.endTime2) {params["beginTime"]=this.startTime2params["endTime"]=this.endTime2}uniapp select被table遮擋
.uni-table-scroll{overflow-x: unset;}this.$set解決新增的對(duì)象屬性沒有響應(yīng)式(computed無效)
? this.$set(this.rowData,'coupon',newVal * num || 0)// 優(yōu)惠金額
圖片
uniapp展示本地圖片使用image>標(biāo)簽都可以展示圖片。但是<img>標(biāo)簽在網(wǎng)頁端和真機(jī)模擬都不可以展示圖片。
路徑直接為 /static/… 不需要相對(duì),不需要@符號(hào)。直接從/static目錄往下寫就行了
數(shù)組
新增元素
- arr.splice(1,0,xx)
- arr.push(xx)
- arr.unshfit(xx)
在使用 <script setup> 的單文件組件中,導(dǎo)入的組件可以直接在模板中使用,無需注冊(cè)
掉起撥打電話接口
<a :href="'tel:' + item.VehiclenoCarManTel">{{item.VehiclenoCarManTel}}</a>
devtools–給你的vue3項(xiàng)目的main.js加上這一句
app.config.devtools = true
?vue 循環(huán)一定要弄key
- 要不然順序變化時(shí)會(huì)出現(xiàn)錯(cuò)誤
js 計(jì)算精度問題
自己寫公共方法:
/**** 加**/add(arg1, arg2) {? var r1, r2, m, c;? try {? r1 = arg1.toString().split(".")[1].length;? } catch (e) {? r1 = 0;? }? try {? r2 = arg2.toString().split(".")[1].length;? } catch (e) {? r2 = 0;? }? c = Math.abs(r1 - r2);? m = Math.pow(10, Math.max(r1, r2));? if (c > 0) {? var cm = Math.pow(10, c);? if (r1 > r2) {? arg1 = Number(arg1.toString().replace(".", ""));? arg2 = Number(arg2.toString().replace(".", "")) * cm;? } else {? arg1 = Number(arg1.toString().replace(".", "")) * cm;? arg2 = Number(arg2.toString().replace(".", ""));? }? } else {? arg1 = Number(arg1.toString().replace(".", ""));? arg2 = Number(arg2.toString().replace(".", ""));? }? return (arg1 + arg2) / m;},/**** 減**/sub(arg1, arg2) {? var r1, r2, m, n;? try {? r1 = arg1.toString().split(".")[1].length;? } catch (e) {? r1 = 0;? }? try {? r2 = arg2.toString().split(".")[1].length;? } catch (e) {? r2 = 0;? }? m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //動(dòng)態(tài)控制精度長度? n = r1 >= r2 ? r1 : r2;? return Number(((arg1 * m - arg2 * m) / m).toFixed(n));},/**** 乘**/mul(arg1, arg2) {? var m = 0,? s1 = arg1.toString(),? s2 = arg2.toString();? try {? m += s1.split(".")[1].length;? } catch (e) {}? try {? m += s2.split(".")[1].length;? } catch (e) {}? return (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) / Math.pow(10, m);},/**** 除**/div(arg1, arg2) {? var t1 = 0,? t2 = 0,? r1,? r2;? try {? t1 = arg1.toString().split(".")[1].length;? } catch (e) {}? try {? t2 = arg2.toString().split(".")[1].length;? } catch (e) {}? r1 = Number(arg1.toString().replace(".", ""));? r2 = Number(arg2.toString().replace(".", ""));? return (r1 / r2) * Math.pow(10, t2 - t1);},或者xe-utils 解決 js 加減乘除精度問題
善于使用對(duì)象處理(存儲(chǔ))多數(shù)據(jù)
let obj = {} obj[key] = xx?一定一定要記得復(fù)雜數(shù)據(jù)類型的特殊性,需求如果是不改變?cè)瓟?shù)據(jù)一定要深拷貝
// 一般使用 JSON.stringify 進(jìn)行拷貝---在獲取的時(shí)候用JSON.parse來解構(gòu)就行了在用store存儲(chǔ)、作為參數(shù)傳遞過去、賦值等等操作一定要注意???removeEventListener
addEventListener 之后一定要記得 removeEventListener- 取消對(duì)一個(gè)全局事件的監(jiān)聽。
插件的結(jié)束時(shí)期
數(shù)據(jù)傳輸 傳過去=》再傳回來(用 uni.navigateTo)
插件使用
???回調(diào)函數(shù)里面如果需要用到 this 記得該回調(diào)函數(shù)一定得寫成箭頭函數(shù)
存儲(chǔ)
要記得 JSON.stringfy 再存儲(chǔ)
uni.setStorageSync(app_user_timestamp, JSON.stringify(Date.now())) //設(shè)置時(shí)間戳uniapp FormData 形式的參數(shù)得更改請(qǐng)求頭
if (isFormData) _header['Content-Type'] = 'application/x-www-form-urlencoded'// 傳遞的參數(shù)是對(duì)象對(duì)象
對(duì)象一整個(gè)賦值會(huì)改不到數(shù)據(jù),要用 . 來更改屬性值
搜索定位功能
uni.pageScrollTo({scrollTop: this.$refs[res.Data.BillInfo.BillNo][0].$el.offsetTop-310,duration: 0});v-for涉及到增刪改查時(shí)一定好設(shè)置一個(gè)唯一的id?
公共的變量/函數(shù)/組件寫在hooks.js里面
使多個(gè)地方可用到,復(fù)用性極強(qiáng)
一整個(gè)對(duì)象賦值改不到原始的對(duì)象,而是直接改了對(duì)象的數(shù)組
-
要是想改掉原來對(duì)象的屬性值,則需要:
- for (let key in this.bjFormFields1) {this.bjFormFields1[key] = this.rowData[key]}
請(qǐng)求接口報(bào)錯(cuò)時(shí),看看是不是多了個(gè)id的屬性,這樣有時(shí)會(huì)報(bào)錯(cuò)
?computed要實(shí)現(xiàn)一定要在script里面用或者在視圖里面用,不要然會(huì)不起作用!!!
vue2對(duì)象和數(shù)組變化一定要符合(數(shù)組:增刪改查,對(duì)象:.xx = )規(guī)則才能有響應(yīng)式,才可以正常進(jìn)行計(jì)算以及watch
涉及到 ref 一定要注意有無 v-if(初始沒有渲染dom)
樣式
.out{background-image: linear-gradient(135deg, #b78666ff 16%, #ffe6d5ff 10%, #fff);background-size: 80% 100%;background-repeat: no-repeat;padding: 6px;.in {border-left: 4px solid #fff;padding-left: 8px;color: #fff;}}總結(jié)
以上是生活随笔為你收集整理的前端技巧总结---持续更新的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IP MAC捆绑原理及缺陷的讨论
- 下一篇: AcFun_API 之 分页读取番剧列表