1JS中的函數節流 2.前端開發環境和生產環境() 3 製造假數據來模擬後端接口
2.前端開發環境和生產環境()
3 製造假數據來模擬後端接口)
1JS中的函數節流(轉自https://segmentfault.com/a/1190000019577510)
一、什麼是函數節流(
概念:限制一個函數在一定時間內只能執行一次。
舉個栗子,坐火車或地鐵,過安檢的時候,在一定時間(例如10秒)內,只允許一個乘客通過安檢入口,以配合安檢人員完成安檢工作。上例中,每10秒內,僅允許一位乘客通過,分析可知,“函數節流”的要點在於,在 一定時間 之內,限制 一個動作 只 執行一次 。
二、爲什麼需要函數節流
前端開發過程中,有一些事件或者函數,會被頻繁地觸發(短時間按內多次觸發),最常見的例如,onresize,scroll,mousemove ,mousehover 等,這些事件的觸發頻率很高,不做限制的話,有可能一秒之內執行幾十次、幾百次,如果在這些函數內部執行了其他函數,尤其是執行了操作 DOM 的函數(瀏覽器操作 DOM 是很耗費性能的),那不僅會造成計算機資源的浪費,還會降低程序運行速度,甚至造成瀏覽器卡死、崩潰。這種問題顯然是致命的。
除此之外,重複的 ajax 調用不僅可能會造成請求數據的混亂,還會造成網絡擁塞,佔用服務器帶寬,增加服務器壓力,顯然這個問題也是需要解決的。
三、函數節流如何解決上述問題
根據上面對問題的分析,細細思索,問題的解決方案就呼之欲出了。
主要實現思路就是通過 setTimeout 定時器,通過設置延時時間,在第一次調用時,創建定時器,先設定一個變量true,寫入需要執行的函數。第二次執行這個函數時,會判斷變量是否true,是則返回。當第一次的定時器執行完函數最後會設定變量爲false。那麼下次判斷變量時則爲false,函數會依次運行。目的在於在一定的時間內,保證多次函數的請求只執行最後一次調用。
四、函數節流的代碼實現
根據以上分析,我們對“函數節流”進行代碼實現,如下:
(1)方法一:時間戳方案
// 時間戳方案
function throttle(fn,wait){
var pre = Date.now();
return function(){
var context = this;
var args = arguments;
var now = Date.now();
if( now - pre >= wait){
fn.apply(context,args);
pre = Date.now();
}
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("mousemove",throttle(handle,1000));
(2)方法二:定時器方案
// 定時器方案
function throttle(fn,wait){
var timer = null;
return function(){
var context = this;
var args = arguments;
if(!timer){
timer = setTimeout(function(){
fn.apply(context,args);
timer = null;
},wait)
}
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("mousemove",throttle(handle,1000));
以上兩種方法本人都親自測試過,小夥伴們可以放心食用(注意,例子中函數觸發方式爲“ mousemove ”,鼠標在頁面上移動,觀察瀏覽器控制檯的變化),自己運行代碼體驗後,自然會更深刻的理解 “函數節流” 。
五、函數節流的使用場景
到此爲止,相信各位應該對函數節流有了一個比較詳細的瞭解,那函數節流一般用在什麼情況之下呢?
懶加載、滾動加載、加載更多或監聽滾動條位置;
百度搜索框,搜索聯想功能;
防止高頻點擊提交,防止表單重複提交;
目前遇到過的使用場景就是這些了,不過理解了原理,小夥伴可以把它運用在需要用到它的任何場合,提高代碼質量。
總結
使用“函數節流”的主要目的,是爲了優化程序性能,提高用戶體驗,不過最主要的爲了節約計算機資源,推薦在合適的場合使用它,才能達到它應有的效果,切忌濫用哦!
2.前端開發環境和生產環境(https://blog.csdn.net/weixin_30502157/article/details/101924594?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2)
在項目開發的時候,我們通常會將程序分爲開發環境和生產環境(或者叫線上環境),開發環境通常指的是我們正在開發的這個階段所需要的一些環境配置,也就是方便我們開發人員調試開發的一種環境;生產環境通常指的是我們將程序開發完成經過測試之後無明顯異常準備發佈上線的環境,也可以理解爲用戶可以正常使用的就是生產環境;
當然開發環境和生產環境在配置方面的需求是不一樣的,但是有共同點:
開發環境的需求:
模塊熱更新 (本地開啓服務,實時更新)
sourceMap (方便打包調試)
接口代理 (配置proxyTable解決開發環境中的跨域問題)
代碼規範檢查 (代碼規範檢查工具)
生產環境的需求:
提取公共代碼
壓縮混淆(壓縮混淆代碼,清除代碼空格,註釋等信息使其變得難以閱讀)
文件壓縮/base64編碼(壓縮代碼,減少線上環境文件包的大小)
去除無用的代碼
開發環境和生產環境的共同需求:
同樣的入口
同樣的代碼處理(loader處理)
同樣的解析配置
在我們搭建好Vue-cli腳手架之後,我們的build文件夾會分別自動的生成webpack.base.conf.js、webpack.dev.conf.js、webpack.prod.conf.js
三個webpack配置文件;
webpack.base.conf.js
:webpack的開發環境和生產環境的共有配置(開發環境和生產環境都是需要執行的配置)
webpack.dev.conf.js
:webpack的開發環境的特有配置(只在開發環境中執行,生產環境中不執行)
webpack.prod.conf.js
:webpack的生產環境的特有配置(只在生產環境中執行,開發環境中不執行)
我們爲什麼要區分開發環境和生產環境呢?
因爲一個項目的開發過程中肯定不會是一個版本開發完之後就立馬上線,開發是必需,上線是目的;在開發的過程中會有各種各樣的問題,比如開發環境中跨域、開發環境和生產環境因環境不同而產生的未知奇葩錯誤等等都是會時常發生的,我們區分環境的目的就是爲了讓開發人員在開發的過程中可以方便調試,保持高效的開發;讓程序在生產環境中正常有效的運行;
webpack.base.conf.js配置
const path = require('path');
//清除build/dist文件夾文件
const CleanWebpackPlugin = require('clean-webpack-plugin');
//生成創建Html入口文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
//將css提取到單獨的文件中
const MiniCssExtract = require('mini-css-extract-plugin');
//css壓縮
const OptimizeCss = require('optimize-css-assets-webpack-plugin');
//壓縮js文件
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
//引入webpack
const webpack = require('webpack');
module.exports = {
//webpack 入口文件
entry: './src/index.js',
//webpack 輸出文件配置
output: {
//輸出文件路徑
path: path.resolve(__dirname, 'dist'),
//輸出文件名
filename: 'k-editor.[hash:8].js',
},
//配置插件
plugins: [
//使用插件清除dist文件夾中的文件
new CleanWebpackPlugin({
path: './dist'
}),
//使用插件生成Html入口文件
new HtmlWebpackPlugin({
//模板文件路徑
template: "./src/index.html",
//模板文件名
filename: "index.html",
minify: {
removeAttributeQuotes: true, //刪除雙引號,
collapseWhitespace: true, //壓縮成一行,
},
hash: true
}),
//提取css到style.css中
new MiniCssExtract({
filename: 'style.css'
}),
],
resolve: {
// modules: [path.resolve('node_modules')],//只在當前目錄下查找
alias: { //別名
'bootstrap': 'bootstrap/dist/css/bootstrap.css',
},
// mainFields: ['style', 'main'],//優先尋找style,
// mainFiles: [],//入口文件的名字,默認index.js
// extensions: ['js', 'css', 'json', 'vue']//擴展名順序
},
//loader加載器模塊配置
module: {
rules: [
{
//正則表達式匹配.css爲後綴的文件
test: /\.css$/,
//使用loader
use: [
MiniCssExtract.loader,
'css-loader',
{
loader: "postcss-loader"
},
]
//正則表達式匹配.less爲後綴的文件
//使用lodaer來處理
}, {
test: /\.less$/,
use: [
MiniCssExtract.loader,
'css-loader',
{
loader: "postcss-loader"
},
'less-loader'
]
},
/* {
test: /\.js$/,
//不包括node_modules
exclude: /node_modules/,
use: [{
loader: "eslint-loader",
options: {
enforce: 'pre' //強制更改順序,pre 前 post 後
}
}],
},*/
{
test: /\.js$/, //普通的loader
//不包括node_modules
exclude: /node_modules/,
use: [{
loader: "babel-loader"
}]
},
{
test: /\.html$/,
use: ['html-withimg-loader']
},
{
test: /\.(gif|png|jpg)$/,
use: [{
loader: "url-loader",
options: {
//圖片小於10kb就是圖片地址,大於正常打包成base64格式編碼
limit: 10000,
//輸出路徑
outputPath: 'img/'
}
}]
}
]
},
};
webpack.dev.conf.js:
//引入webpack-merge插件進行合併
const {merge} = require('webpack-merge');
//引入webpack.base.conf.js文件
const base = require('./webpack.base.conf');
//引入webpack
const webpack = require('webpack');
//進行合併,將webpack.base.conf.js中的配置合併到這
module.exports = merge(base, {
//模塊參數
mode: 'development',
devServer: {
contentBase: './dist',
//端口號
port: '8383',
inline: true,
historyApiFallback: true,//在開發單頁應用時非常有用,它依賴於HTML5 history API,如果設置爲true,所有的跳轉將指向index.html
hot: true//允許熱加載
},
//啓用source-map方便調試
devtool: 'source-map',
plugins: [
//定義全局變量
new webpack.DefinePlugin({
//這裏必須要解析成字符串進行判斷,不然將會被識別爲一個變量
DEV: JSON.stringify('dev')
})
]
});
webpack.prod.conf.js:
const {merge} = require('webpack-merge');
const base = require('./webpack.base');
const path = require('path');
const OptimizeCss = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const webpack = require('webpack');
module.exports = merge(base, {
mode: 'production',
optimization: {
minimizer: [
//壓縮CSS代碼
new OptimizeCss(),
//壓縮js代碼
new UglifyJsPlugin({
//啓用文件緩存
cache: true,
//使用多線程並行運行提高構建速度
parallel: true,
//使用 SourceMaps 將錯誤信息的位置映射到模塊
sourceMap: true
})
]
},
plugins:[
//使用插件定義全局變量DEV
new webpack.DefinePlugin({
DEV:JSON.stringify('production')
})
]
});
最後在配置一下package.json文件就可以了:
"scripts": {
"test": "npm run test",
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
如何區分開發環境和生產環境呢?
在node中,我們有一個對象process對象,它裏面包括的一些信息,env和它的一些屬性,當然NODE_ENV是我們自己加上去的自定義屬性,用來區分環境變量,也就是通過這個變量來進行區別是開發環境還是生產環境;但是有個問題,不同電腦上設置的方式是不一樣的,所以cross-env就來了,它可以跨平臺設置環境和使用環境變量。
npm install cross-env
我們在webpack.base.conf.js文件中修改代碼:
const NODE_ENV=process.env.NODE_ENV;
console.log(NODE_ENV);
然後我們修改package.json文件:
//–config是可以設置我們執行哪個webpack文件,默認是執行webpack.config.js,但是我們現在修改文件名了,所以我們要設置一下
"build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.dev.js"
就這樣,我們就實現了利用webpack來區分開發環境和生產環境,當我們用npm run dev運行的時候就是開發環境,當我們運行npm run build的時候就是構建生產環境打包;
3 製造假數據來模擬後端接口呢(轉自:https://blog.csdn.net/thankszmy/article/details/79570613)
在我們的生產實際中,後端的接口往往是較晚才會出來,並且還要寫接口文檔,於是我們的前端的許多開發都要等到接口給我們才能進行,這樣對於我們前端來說顯得十分的被動,於是有沒有可以製造假數據來模擬後端接口呢,答案是肯定的。應該有人通過編寫json文件來模擬後臺數據,但是很侷限,比如增刪改查這些接口怎麼實現呢,於是今天我們來介紹一款非常強大的插件Mock.js,可以非常方便的模擬後端的數據,也可以輕鬆的實現增刪改查這些操作。
1.一個簡單的例子:
複製代碼
Mock.mock('http://123.com',{
'name|3':'fei',//這個定義數據的模板形式下面會介紹
'age|20-30':25,
})
$.ajax({
url:'http://123.com',
dataType:'json',
success:function(e){
console.log(e)
}
})
複製代碼
在這個例子中我們截獲地址爲http://123.com返回的數據是一個擁有name和age的對象,那麼ajax返回的數據就是Mock定義的數據,返回的數據格式如下:
{
name:'feifeifei',
age:26,
}
至於上面的定義模板數據的格式是什麼意思,下面就給大家介紹。
2.介紹如何定義數據
數據模板中的每個屬性由 3 部分構成:屬性名、生成規則、屬性值:
// 屬性名 name
// 生成規則 rule
// 屬性值 value
'name|rule': value
1.'name|min-max': string 通過重複
string
生成一個字符串,重複次數大於等於
min
,小於等於
max
例子:'lastName|2-5':'jiang', 重複jiang這個字符串 2-5 次
2.'name|count': string 通過重複
string
生成一個字符串,重複次數等於
count
例子:'firstName|3':'fei', 重複fei這個字符串 3 次,打印出來就是'feifeifei'。
3.'name|min-max': number 生成一個大於等於
min
、小於等於
max
的整數,屬性值
number
只是用來確定類型。
例子:'age|20-30':25, 生成一個大於等於 20、小於等於 30 的整數,屬性值 25 只是用來確定類型
4.'name|+1': number 屬性值自動加 1,初始值爲
number
例子:'big|+1':0, 屬性值自動加 1,初始值爲 0,以後每次請求在前面的基礎上+1
5.'name|min-max.dmin-dmax': number 生成一個浮點數,整數部分大於等於
min
、小於等於
max
,小數部分保留
dmin
到
dmax
位。
例子:'weight|100-120.2-5':110.24, 生成一個浮點數,整數部分大於等於 100、小於等於 120,小數部分保留 2 到 5 位
6.'name|1': boolean 隨機生成一個布爾值,值爲 true 的概率是 1/2,值爲 false 的概率同樣是 1/2
例子:'likeMovie|1':Boolean, 隨機生成一個布爾值,值爲 true 的概率是 1/2,值爲 false 的概率同樣是 1/2。
7.屬性值是對象:var obj={'host':'www.baidu','port':'12345','node':'selector'}
7-1.'name|count': object 從屬性值
object
中隨機選取
count
個屬性。
例子:'life1|2':obj, 從屬性值 obj 中隨機選取 2 個屬性
7-2.'name|min-max': object 從屬性值
object
中隨機選取
min
到
max
個屬性
例子:'life1|1-2':obj, 從屬性值 obj 中隨機選取 1 到 2 個屬性。
8.屬性值是數組:var arr=['momo','yanzi','ziwei']
8-1.'name|1': array 從屬性值
array
中隨機選取 1 個元素,作爲最終值
例子:'friend1|1':arr, 從數組 arr 中隨機選取 1 個元素,作爲最終值。
8-2.'name|+1': array 從屬性值
array
中順序選取 1 個元素,作爲最終值。
例子:'friend2|+1':arr, 從屬性值 arr 中順序選取 1 個元素,作爲最終值,第一次就是'momo',第二次請求就是'yanzi'
8-3.'name|count': array 通過重複屬性值
array
生成一個新數組,重複次數爲
count
。
例子:'friend3|2':arr, 重複arr這個數字2次作爲這個屬性值,得到數據應該是['momo','yanzi','ziwei','momo','yanzi','ziwei']
8-4.'name|min-max': array 通過重複屬性值
array
生成一個新數組,重複次數大於等於
min
,小於等於
max
例子:'friend3|2-3':arr,//通過重複屬性值 arr 生成一個新數組,重複次數大於等於 2,小於等於 3
3.實際的ajax請求例子:
複製代碼
var arr=['momo','yanzi','ziwei']
var obj={
'host':'www.baidu',
'port':'12345',
'node':'selector'
}
Mock.mock('http://www.bai.com',{
'firstName|3':'fei',//重複fei這個字符串 3 次,打印出來就是'feifeifei'。
'lastName|2-5':'jiang',//重複jiang這個字符串 2-5 次。
'big|+1':0, //屬性值自動加 1,初始值爲 0
'age|20-30':25,//生成一個大於等於 20、小於等於 30 的整數,屬性值 25 只是用來確定類型
'weight|100-120.2-5':110.24,//生成一個浮點數,整數部分大於等於 100、小於等於 120,小數部分保留 2 到 5 位。
'likeMovie|1':Boolean,//隨機生成一個布爾值,值爲 true 的概率是 1/2,值爲 false 的概率同樣是 1/2。
'friend1|1':arr,//從數組 arr 中隨機選取 1 個元素,作爲最終值。
'friend2|+1':arr,//從屬性值 arr 中順序選取 1 個元素,作爲最終值
'friend3|2-3':arr,//通過重複屬性值 arr 生成一個新數組,重複次數大於等於 2,小於等於 3。
'life1|2':obj,//從屬性值 obj 中隨機選取 2 個屬性
'life1|1-2':obj,//從屬性值 obj 中隨機選取 1 到 2 個屬性。
'regexp1':/^[a-z][A-Z][0-9]$/,//生成的符合正則表達式的字符串
})
$.ajax({
url:'http://www.bai.com',
dataType:'json',
success:function(e){
console.log(e)
}
})
複製代碼
4.如何實現數據 增 刪 改 查 的模擬數據接口
下面我就模擬後端刪除功能的接口實現
複製代碼
/*模擬刪除數據的方式*/
var arr=[
{name:'fei',age:20,id:1},
{name:'liang',age:30,id:2},
{name:'jun',age:40,id:3},
{name:'ming',age:50,id:4}
]
Mock.mock('http://www.bai.com','delete',function(options){
var id = parseInt(options.body.split("=")[1])//獲取刪除的id
var index;
for(var i in arr){
if(arr[i].id===id){//在數組arr裏找到這個id
index=i
break;
}
}
arr.splice(index,1)//把這個id對應的對象從數組裏刪除
return arr;//返回這個數組,也就是返回處理後的假數據
})
$.ajax({
url:'http://www.bai.com',
type:"DELETE",
data:{
id:1//假設需要刪除id=1的數據
},
dataType:'json',
success:function(e){
console.log(e)
}
})