Web前端開發過程踩過的坑以及一些小方法技巧(持續更新)

1、iOS上瀏覽器使用jQuery不容許事件代理到document上

$(document).on("click", "選擇器", function(){});

以上綁定可能會出現點擊失效的狀況。解決方法就是在這些代碼前加一串代碼:css

$(body>*).bind("click", function(){....});

2、移動端點擊輸入框(input)禁止手機輸入法鍵盤彈出

在移動端頁面開發時,咱們有時候常常會用到本身定義的輸入鍵盤,而不想自帶鍵盤彈出,那麼能夠在點擊事件中加入如下代碼:html

$("選擇器").click(function(){ document.activeElement.blur(); });

3、在iOS平臺上input的button類型會帶有默認樣式。

這個在Android上使用如下代碼就能夠解決,可是iOS不起做用。vue

border: none;
outline: none;
background-color: 顏色;

可是在iOS上須要加一個:node

-webkit-appearance: none;

這個屬性一樣適用於Android。android

4、移動端Retina屏(iOS) 1px的解決方案

這個我在網上找到許多解決方案,這裏就直接放連接了webpack


移動端 Retina屏 各大主流網站1px的解決方案
如何在Vue項目中使用vw實現移動端適配

5、iOS瀏覽器在設置overflow: scroll;後滑動不流暢,感受像是卡頓

這個目前在Android和PC上沒得問題,可是iOS上有問題,解決方法就是加上屬性:ios

-webkit-overflow-scrolling: touch;

參考資料:git

【兼容性】ios上設置overflow: scroll不滾動bug
iOS Safari瀏覽器上overflow: scroll元素沒法滑動bug解決方法整理
iOS safari瀏覽器上overflow: scroll元素沒法滾動bug深究
解決頁面使用overflow: scroll在iOS上滑動卡頓的問題

6、元素在設置爲display:inline-block;後元素之間會產生間距

解決方法就是在包含這些元素的父元素上設置CSS屬性font-size: 0;github

7、Angular CLI和Vue CLI打包的項目上線不在根目錄出現資源找不到問題!

  • 對於ng,在package.jsonbuild後面改爲ng build --base-href ./
  • 對於Vue,若是CLI工具是3.3如下版本,在vue.config.js中加入如下代碼:
module.exports = {
  baseUrl: process.env.NODE_ENV === 'production'
    ? '/henjievue/'
    : '/'
}
3.3以上的版本加入如下代碼:
module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
    ? '/henjievue/'
    : '/'
}

8、Angular CLI開發對於assets文件的處理問題。

assets文件夾裏面的內容在build後不參與打包,僅僅完整複製,因此在開發過程當中路徑的寫法按絕對路徑寫就行了,以下代碼:web

<img src="assets/index/ng.png">

9、解決ios10及以上Safari沒法禁止縮放的問題

//如下代碼是爲了解決在iOS 10系統以後設置meta來禁止縮放失效的問題
      window.onload = function() {
        // 阻止雙擊放大
        document.addEventListener('touchstart', function(event) {
            if (event.touches.length > 1) {
                event.preventDefault();
            }
        });
        var lastTouchEnd = 0;
        document.addEventListener('touchend', function(event) {
            var now = (new Date()).getTime();
            if (now - lastTouchEnd <= 300) {
                event.preventDefault();
            }
            lastTouchEnd = now;
        }, false);

        // 阻止雙指放大
        document.addEventListener('gesturestart', function(event) {
            event.preventDefault();
        });
      }

10、在最新的Vue腳手架工具下(3.x以上)使用2.x腳手架使用的搭建目錄

在安裝好最新的vue腳手架狀況下,使用如下命令來安裝一個額外工具:

npm install -g @vue/cli-init

以後就可使用如下命令生成老的項目目錄:

vue init webpack 項目名

11、Vue CLi 3.0腳手架工具關閉ESlint檢查

在vue.config.js中加一句話:

module.exports = {
  baseUrl: process.env.NODE_ENV === 'production'
    ? '/henjievue/'
    : '/',
  lintOnSave: false //加這句話能夠關閉ESlint
}

12、JS的循環裏面有異步請求如何保證異步請求按次序執行

這個不能用循環來解決,應該用遞歸來實現,或者用Promise.all來實現,這裏僅提供遞歸解決方法。

(function loop(index){
  axios.get("http://192.168.12.101:3000/news/list"+"?pageNum="+page[index]).then((response)=>{
    console.log(response);
    if(++index < page.length){
      loop(index);
    }
    else{
      console.log("所有執行完畢")
    }
  }).catch((error)=>{
    console.log(error);
  })
})(0)

十3、vue裏面路由的路由守衛的beforeRouteEnter的鉤子函數沒法獲取到vue實例(this)

這個鉤子函數裏不能直接使用this來獲取vue實例,或者報undefined錯誤,解決方法以下:

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 由於當鉤子執行前,組件實例還沒被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,可是該組件被複用時調用
    // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
    // 能夠訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 能夠訪問組件實例 `this`
  }
}
//以上爲解釋。如下爲解決方法
beforeRouteEnter(to, from, next){ 
    next((vm)=>{
        console.log(vm);
        if(from.path == '/'){
            vm.isShowAppr = false;
        }
    });
},

十4、在Chrome瀏覽器下img標籤在沒有圖片的狀況下會顯示邊框的問題?

解決方法以下,添加一段css代碼便可:

img[src=""], img:not([src]){
    opacity: 0;
}

十5、v-if綁定一個數組變量,改變變量的值並無使v-if起做用

問題:當v-if綁定一個數組變量,改變變量的值並無使v-if起做用。引出個問題因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:
1.當你利用索引直接設置一個項時
2.當你修改數組的長度時
緣由:網上總結:

  1. Vue檢測數據的變更是經過Object.defineProperty實現的,因此沒法監聽數組的添加操做是能夠理解的,由於是在構造函數中就已經爲全部屬性作了這個檢測綁定操做。
  2. Vue 中是經過對 每一個鍵設置 getter/setter 來實現響應式的,開發者使用數組,目的每每是遍歷,此時調用 getter 開銷太大了,因此 Vue 不在數組每一個鍵上設置,而是在數組上定義 ob ,而且替換了 push 等等可以影響原數組的原型方法。從vue源碼能夠清晰看到,Vue 跳過了對數組每一個鍵設置響應式的過程,而是直接對值進行遞歸設置響應式。
解決:

第一類問題:
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
vm.$set(vm.items, indexOfItem, newValue)
eg: this.$set(this.isShowOKimg, index, true);
第二類問題:
vm.items.splice(newLength)

v-if綁定一個數組變量,改變變量的值並無使v-if起做用

十6、表單中onchange事件的觸發條件

input輸入框的onchange事件,要在 input 失去焦點的時候纔會觸發;在輸入框內容變化的時候不會觸發change,當鼠標在其餘地方點一下才會觸發;onchange 事件也可用於單選框與複選框改變後觸發的事件。

onchange event 全部主要瀏覽器都支持;
onchange 屬性可使用於:<input>, <select>, 和 <textarea>。

  • input事件

oninput 事件在用戶輸入時觸發,它是在元素值發生變化時當即觸發;該事件在 <input> 或 <textarea> 元素的值發生改變時觸發。

  • onpropertychange事件

onpropertychange會實時觸發,會在元素的屬性改變時就觸發事件。當元素disable=true時不會觸發。缺陷:只在IE 下支持,其餘瀏覽器不支持,用oninput來解決。

input輸入框的input事件和change事件

十7、vue中this.$route與this.$router的區別

一、this.$router

全局的路由實例,是router構造方法的實例。在 Vue 實例內部,你能夠經過 $router 訪問路由實例,

  • 注意this.$route和this.$router均不能在使用Vue.extend()構造器所構造的彈框等實例裏面取到

有go、push、replace、forward等方法
一、this.$router.push()
// 字符串
      this.$router.push('home')
// 對象
      this.$router.push({ path: 'home' })
// 命名的路由
      this.$router.push({ name: 'user', params: { userId: 123 }})
// 帶查詢參數,變成 /register?plan=123
      this.$router.push({ path: 'register', query: { plan: '123' }})
二、this.$router.replace()
    一樣是跳轉到指定的url,可是這個方法不會向history裏面添加新的記錄,點擊返回,會跳轉到上上一個頁面。上一個記錄是不存在的。
三、this.$router.go()
    相對於當前頁面向前或向後跳轉多少個頁面,相似 window.history.go(n)。n可爲正數可爲負數。正數返回上一個頁面

二、this.$route

表示當前激活的路由的狀態信息,包含了當前 URL 解析獲得的信息,還有 URL 匹配到的 route records(路由記錄)。路由信息對象:即$router會被注入每一個組件中,能夠利用它進行一些信息的獲取。
**1.$route.path**
      字符串,對應當前路由的路徑,老是解析爲絕對路徑,如 "/foo/bar"。
**2.$route.params**
      一個 key/value 對象,包含了 動態片斷 和 全匹配片斷,
      若是沒有路由參數,就是一個空對象。
**3.$route.query**
      一個 key/value 對象,表示 URL 查詢參數。
      例如,對於路徑 /foo?user=1,則有 $route.query.user == 1,
      若是沒有查詢參數,則是個空對象。
**4.$route.hash**
      當前路由的 hash 值 (不帶 #) ,若是沒有 hash 值,則爲空字符串。錨點
**5.$route.fullPath**
      完成解析後的 URL,包含查詢參數和 hash 的完整路徑。
**6.$route.matched**
      數組,包含當前匹配的路徑中所包含的全部片斷所對應的配置參數對象。
**7.$route.name    當前路徑名字**
**8.$route.meta  路由元信息


router.beforeEach((to, from, next) => {
  // to 和 from 都是 路由信息對象
})
watch: {
  $route(to, from) {
     // to 和 from 都是 路由信息對象
  }
}
this.$router的內容就是new VueRouter({})實例出來的對象(這個在router.js裏面會建立並導出),他們兩個是相同的。

十8、部分ios系統在鍵盤收回時不會將頂起的頁面自動收回

在input的上加一個blur時間,這裏以vue爲例,其它相似

<input @blur="autoscrollBack" v-model="code" type="text" placeholder="請輸入6位驗證碼">

autoscrollBack(){
    window.scroll(0, 0); //自動滾回
}

十9、節流和防抖

一、節流代碼

function throttle(callback, timeSolt){
        var last_time = 0;
        return function(){
            let context = this;
            let args = arguments;
            let now = new Date();
            if(now - last_time >= timeSolt){
                last_time = now;
                callback.apply(context, arguments);
            }
        }
    }
    document.addEventListener('scroll', throttle((e)=>{
        console.log(e.target) //輸出#document
        console.log(this) //輸出window對象
    }, 2000), false);
    注:其實上面addEventListener的回調函數最終執行的是throttle返回的函數

二、防抖代碼

function debounce(callback, timeSolt){
        let timer;
        return function(){
            let context = this;
            let args = arguments;
            if(timer){
                clearTimeout(timer);
            }
            timer = setTimeout(function(){
                callback.apply(context, args);
            }, timeSolt)
        }
    }

    document.addEventListener('scroll', debounce((e)=>{
        console.log(e.target) //輸出#document
        console.log(this)     //輸出window對象
    }, 2000), false)

三、防抖節流結合版

function throttle_and_debounce(callback, timeSolt){
        let last_time;
        let timer;
        return function(){
            let context = this;
            let args = arguments;
            let now = new Date();
            if(now - last_time < timeSolt){
                clearTimeout(timer);
                timer = setTimeout(function(){
                    last_time = now;
                    callback.apply(context, args);
                }, timeSolt)
            }else{
                last_time = now;
                callback.apply(context, args);
            }
        }
    }
    document.addEventListener('scroll', throttle_and_debounce((e)=>{
        console.log(e.target) //輸出#document
        console.log(this)     //輸出window對象
    }, 2000), false)

二10、Js event對象offsetX, clientX, pageX, screenX, layerX, x區別

圖片描述
圖片描述
圖片描述
圖片描述
參考資料

二11、offsetWidth, clientWidth, scrollWidth, innerWidth, outerWidth, pageXOffset等

圖片描述
一、無滾動條時,dom對象的offsetWidth、clientWidth和scrollWidth等
圖片描述
圖片描述
二、有滾動條時,dom對象offsetWidth、clientWidth 和 scrollWidth等
圖片描述
圖片描述
三、window對象的 outerWidth、innerWidth、pageXOffset 和 screenLeft(screenX)
圖片描述
參考資料

二12、vscode設置終端類型

一、命令面板(Ctrl+Shift+P)中,輸入select選如圖所示的選項
圖片描述
二、以後選擇目標Shell。
圖片描述
參考資料

二十3、爲git和github desktop設置代理

一、爲git設置代理,這裏以設置http協議爲例,ssh暫未研究
在須要使用代理的項目下面使用 git bash 以下命令進行設置,我這裏代理是127.0.0.1:8080

git config http.proxy http://127.0.0.1:8080 # 也能夠是uri:port形式
這個是不須要鑑權的代理設置,若是須要鑑權,可能須要添加用戶名密碼信息:
git config http.proxy http://username:password@127.0.0.1:8080
若是git的全部項目都須要啓用代理,那麼能夠直接啓用全局設置:
git config --global http.proxy http://127.0.0.1:8080
爲了確認是否已經設置成功,可使用 --get 來獲取:
git config --get --global http.proxy
這樣能夠看到你設置在global的 http.proxy 值。 須要修改的時候,再次按照上面的方法設置便可,git默認會覆蓋原有的配置值。當咱們的網絡出現變動時,可能須要刪除掉原有的代理配置,此時須要使用 --unset 來進行配置:
git config --global --unset http.proxy
在命令以後,指定位置的設置值將會被清空,你能夠再次使用 --get 來查看具體的設置狀況。若是使用了HTTPS,肯呢個會碰到HTTPS 證書錯誤的狀況,好比提示: SSL certificate problem 。。。,此時,能夠嘗試將 sslVerify 設置爲 false :
git config --global http.sslVerify false
到此設置完畢。

參考資料

二、爲github desktop設置代理
這個設置起來相對簡單,以win 10爲例,找到如下路徑C:\Users\你的用戶名,找到名爲.gitconfig文件,添加如下內容:

[http]
    proxy = http://127.0.0.1:8080

設置完成後保存便可。
參考資料

二十4、css實現單行、多行文本溢出顯示省略號的方法

一、單行省略號

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
注:這種方式通常都須要給固定寬度

二、多行省略號(這個屬性只合適WebKit瀏覽器)

dispaly: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
-webkit-line-clamp: 2; //這個顯示幾行
overflow: hidden;

三、多瀏覽器兼容方案

p {
    position:relative;
    line-height:1.4em; //要顯示三行的話那麼元素的高度就是行高的3倍,其它狀況以此類推。
    /* 3 times the line-height to show 3 lines */
    height:4.2em;
    overflow:hidden;
}
p::after {
    content:"...";
    font-weight:bold;
    position:absolute;
    bottom:0;
    right:0;
    padding:0 20px 1px 45px;

}

參考資料

二十5、JS裏面生成隨機整數

首先要了解幾個函數

一、 Math.random()生成 [0, 1)之間的數。
二、 Math.round()將小數四捨五入。
三、 Math.floor()下取整。
四、 Math.ceil()上取整。

一、生成[min, max]之間的整數。

var result = Math.round(Math.random() * (max - min)) + min;

二、生成[min, max)之間的整數。

var result = Math.floor(Math.random() * (max - min)) + min;

三、生成(min, max]之間的整數。

var result = Math.ceil(Math.random() * (max - min + 1)) + min;

三、生成(min, max)之間的整數。

var result = Math.floor(Math.random() * ((max-1) - (min+1))) + (min+1);至關於 min+1 ≤ r ≤ max - 1

參考資料
參考資料

二十6、Babel相關的概念

  • @babel/core: babel的核心,核心的api都在包含在這裏。
  • @babel/cli: 命令行工具,經過命令對js文件進行轉換的工具。
  • @babel/perset-env: 指定轉換的工做環境。
  • @babel/polyfill: 至關於一個填充,由於babel自己只支持轉換箭頭函數、結構賦值這些語法糖類的語法,而一些新的API或者Promise函數等是沒法轉換的。@babel/polyfill就是解決這個問題的。
  • babel-loader: webpack的加載器,用於調用@babel/core的核心API來完成編譯。

一、@babel/core與babel-core區別

@babel/core是babel 7事後的版本標識,babel-core是之前版本的標識。

二、.babelrc和babel.config.js

.babelrc和babel.config.js均是babel的配置文件,babel.config.js是bebel 7引入的新的方式。
三、@babel/polyfill和@babel/plugin-transform-runtime和@babel/runtime和@babel/runtime-corejs2(都是用來轉換新Api的)
  • (1)@babel/polyfill:babel-polyfill則是經過改寫全局prototype的方式實現,比較適合單獨運行的項目。開啓babel-polyfill的方式,能夠直接在代碼中require,或者在webpack的entry中添加,也能夠在babel的env中設置useBuildins爲true來開啓,可是babel-polyfill會有近100K,打包後代碼冗餘量比較大,對於現代的瀏覽器,有些不須要polyfill,形成流量浪費污染了全局對象。
//使用方法一在entry中添加
module.exports = {
    entry: {
        main: ["@babel/polyfill", path.resolve(__dirname, "./src/index.js")]
    }
}
//使用方式二babel.config.js中設置
module.exports = {
    presets: [
        "@babel/preset-env", { "useBuiltIns": true }
    ]
}

  • (2)@babel/runtime和@babel/plugin-transform-runtime:babel-runtime和 babel-plugin-transform-runtime的區別是,至關一前者是手動擋然後者是自動擋,每當要轉譯一個api時都要手動加上require('babel-runtime'),而babel-plugin-transform-runtime會由工具自動添加,主要的功能是爲api提供沙箱的墊片方案,不會污染全局的api,所以適合用在第三方的開發產品中。

  • (3)@babel/runtime-corejs2:plugin-transform-runtime 能夠設置成 false 或者 2,在babel.config.js的配置文件下有如下代碼:
module.exports = {
    preset: ["@babel/preset-env"],
    plugins: [
        "@babel/plugin-transform-runtime", { corejs: 2 }
    ]
}
一、corejs 是一個給低版本的瀏覽器提供接口的庫,如 Promise, map, set 等。在 babel 中你設置成 false 或者不設置,就是引入的是 corejs 中的庫,並且在全局中引入,也就是說侵入了全局的變量。
二、若是你的全局有一個引入,不要讓引入的庫影響全局,那你就須要引把 corejs 設置成 2。
因此一旦你使用了2這個參數就必須引入@babel/runtime-corejs2
三、@babel/plugin-transform-runtime是必須裝的,若是corejs設置爲2的話安裝@babel/runtime-corejs2來代替@babel/runtime,反正設置爲false的話就須要@babel/runtime,根據你的設置來安裝便可。

在babel 7下:

  • babel.config.js 是對整個項目(父子package) 都生效的配置,但要注意babel的執行工做目錄。
  • .babelrc 是對 待編譯文件 生效的配置,子package若想加載.babelrc是須要babel配置babelrcRoots才能夠(父package自身的babelrc是默承認用的)。
  • 任何package中的babelrc尋找策略是: 只會向上尋找到本包的 package.json 那一級。
  • node_modules下面的模塊通常都是編譯好的,請剔除掉對他們的編譯。若有須要,能夠把個例加到 babelrcRoots 中。

默認狀況下.babelrc不做用於子包,那麼在babel.config.js下加入一下babelrcRoots來指定便可。

module.exports = {
      babelrcRoots: ['.', './frontend', './backend'] // 容許這兩個子 package 加載 babelrc 相對配置
    }

一文讀懂 babel7 的配置文件加載邏輯
對babel-transform-runtime,babel-polyfill的一些理解
babel7中 corejs 和 corejs2 的區別
babel preset env配置
babel學習筆記

二十7、window.scrollTo(x, y)與window.scrollBy(x, y)區別。

1.scrollTo()是絕對位置滾動,每次都是相對初始位置(0, 0)位置滾動。
2.scrollBy()是相對位置滾動,相對於上次移動的最後位置移動。

二十8、iOS 12在新iPhone上收起輸入法後頁面不會自動恢復滾動到初始位置(十八的方案用戶體驗不太好,每次都會滾到頂部去)

this.$refs.drawnameInput.addEventListener('blur', function(){
    var currentPosition;
    var speed=1;//頁面滾動距離
    currentPosition=document.documentElement.scrollTop || document.body.scrollTop;
    currentPosition-=speed; 
    window.scrollTo(0,currentPosition);//頁面向上滾動
    currentPosition+=speed; //speed變量
    window.scrollTo(0,currentPosition);//頁面向下滾動
})

二十9、防止頁面被調試的JS代碼

//添加debuger進行反調試
        (function anti_debuger(){
            function testDebuger(){
                var d=new Date();
                debugger;
                if(new Date()-d>10){
                    document.body.innerHTML='<div>年輕人,不要太好奇</div>';
                    return true;
                }
                return false;
            }
         
            function start(){
                while(testDebuger()){
                    testDebuger();
                }
            }
            if(!testDebuger()) {
                window.onblur = function(){
                    setTimeout(function(){
                        start();
                    },500)
                }
            }
            else{
                start();
            }
        })();

如何防止頁面被調試

三10、移動端喚起QQ聊天 (ios android 包含微信、qq內置瀏覽器,不兼容ios10及如下版本(window.open()改爲location.href=''這種就不會存在兼容性問題))(本人測試爲ios safari跳轉到QQ沒問題)

var u = navigator.userAgent;
        var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
        if(isiOS){
          //uin=這個部分就是你要聊天的QQ號
          if(u.toLowerCase().match(/MicroMessenger/i) == "micromessenger"){
            window.open('http://wpa.qq.com/msgrd?v=3&uin=2290747606&site=qq&menu=yes');
          }else{
            window.open('mqqwpa://im/chat?chat_type=wpa&uin=2290747606&version=1&src_type=web&web_src=oicqzone.com')
          }
        }else{
          if(u.toLowerCase().match(/MicroMessenger/i) == "micromessenger"){
            window.open('http://wpa.qq.com/msgrd?v=3&uin=2290747606&site=qq&menu=yes');
          }else{
            window.open('mqqwpa://im/chat?chat_type=wpa&uin=2290747606&version=1&src_type=web&web_src=oicqzone.com');
          }
        }

三11、移動端指定的時間格式。

移動端在使用new Date()生成指定時間的時間戳時,裏面的格式有要求,不然不能正確獲取。
var time = new Date('2019/9/18 18:00') //這個裏面不要使用2019-9-18這種格式,PC端的雖然能夠正常識別。

在IOS平臺慎用Date.parse()方法,這個在ios上支持很差,會失效!

...、設置margin:auto使塊級元素居中,可是水平方向出現了滾動條,body沒有佔滿瀏覽器窗口。

圖片描述

//HTML代碼
<div id="smart">
    <div class="smart-container-one">
        <p style="position: relative; left: 600px;"><img src="img/lazyload-b3704113c8.gif"/></p>
    </div>
</div>

//CSS代碼
#smart>.smart-container-one {
    width: 1240px;
    height: 450px;
    margin: auto;
}

出現這樣的結果就是因爲<p style="position: relative; left: 600px;"><img src="img/lazyload-b3704113c8.gif"/></p>形成的,p元素是塊級元素,定位若是爲relative的話會佔用位置,致使父元素被撐開了。

解決方法有:
1.給p元素設置絕對定位 position: absolute便可。
2.p元素換成內聯元素,如 span
3.把p元素設置爲內聯元素,如 display: inline

注:這兒p標籤包img太業餘了,你們平時寫不要這樣寫,通常用div,菜鳥一枚,還請你們見諒。
相關文章
相關標籤/搜索