關(guān)鍵詞:
create-react-app2.1.1重大改變,授權(quán)登陸登下,( ISO8061時間格式茫孔;UTC,GMT時間 ) ,動效被芳,對象數(shù)組去重缰贝,字符集,base64轉(zhuǎn)碼畔濒,打包去掉.map文件剩晴,location, encodeURIComponent,word-wrap, word-break, white-space, text-overflow侵状,onScroll赞弥, scrollIntoView,嵌套路由趣兄,子路由绽左,滾動平滑css屬性, background艇潭, proxy拼窥,redux-devtools-extension
(一) create-react-app 2.1
默認(rèn)支持sass和scss
只需安裝node-sass即可( yarn add node-sass )默認(rèn)支持css-modules
scss文件命名需要加上module
比如: login.module.scss
如何開啟絕對路徑
1.在根目錄下新建名為.env后綴的文件
2.設(shè)置環(huán)境變量: NODE_PATH=src 即可把src目錄作為根目錄
create-react-app的配置方式是它的webpack配置會自動選取'.env'文件并讀取'NODE_PATH'環(huán)境變量,然后可用于絕對導(dǎo)入.自定義環(huán)境變量在開發(fā)和生產(chǎn)過程中都可以使用蹋凝,因為變量是在構(gòu)建時嵌入的鲁纠,而不是運行時嵌入的,所以你的應(yīng)用程序可以通過'process.env'訪問它的環(huán)境
https://www.imooc.com/article/37421proxy的修改
1.新版proxy代理只支持字符串模式了仙粱,如果是對象需要下載插件
2.http-proxy-middleware
(庫地址) https://github.com/chimurai/http-proxy-middleware
(教程) https://blog.csdn.net/weixin_36094484/article/details/82968545如何使用less
1.安裝less和less-loader
cnpm install less less-loader --save
2.修改webpack.config.dev.js和webpack.config.prod.js
在create-react-app中使用less
(1) 定義變量
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/; ------------------------------- 添加這兩行
const lessModuleRegex = /\.module\.(less)$/; ------------------- 添加這兩行
(2)配置module的rules
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders({ importLoaders: 2 }, 'less-loader'),
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'less-loader'
),
},
- 如何引入antd,并按需加載
1.安裝 cnpm install babel-plugin-import ( 用于按需加載組件代碼和樣式的 babel 插件 )
2.在package.json中
------------或者webpack.config.dev房交,webpack.config.prod 中
------------或者自己新建.babelrc文件
如何引入antd,并按需加載
(1) 在package.json中添加:
"plugins":[["import", {"libraryName": "antd", "style": "css"}]]
"babel": {
"presets": [
"react-app"
],
"plugins":[["import", {"libraryName": "antd", "style": "css"}]] // 添加插件
},
------------
(2) 在 webpack.config.dev(開發(fā)環(huán)境)和 webpack.config.prod 中
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
},
},
},
],
// ["import", {"libraryName": "antd","libraryDirectory": "es","style": "css" }] 添加!7ジ睢候味!
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
// Don't waste time on Gzipping the cache
cacheCompression: false,
},
},
- 如何修改antd的主題顏色 (這里有個巨坑)
https://blog.csdn.net/qwe502763576/article/details/83242823
- 在package.json中修改 plugin
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": true ------------------------ 這里把css改為true
}
]
]
- 在webpack.config.dev.js中修改getStyleLoaders()函數(shù)
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
},
},
];
if (preProcessor) { ---------------------------------- 主要修改這里
let loader = require.resolve(preProcessor);
if (preProcessor === "less-loader") {
loader = {
loader,
options: {
javascriptEnabled: true, ------------------- 關(guān)鍵配置這里
}
}
loaders.push(loader);
}
}
return loaders;
};
- 新建them.less文件,在them.less中引入@import "~antd/dist/antd.less"隔心,再把them.less引入到項目的入口文件index.js中即可
them.less
@import "~antd/dist/antd.less";
@primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 鏈接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 錯誤色
@font-size-base: 14px; // 主字號
@heading-color: rgba(0, 0, 0, .85); // 標(biāo)題色
@text-color: rgba(0, 0, 0, .65); // 主文本色
@text-color-secondary : rgba(0, 0, 0, .45); // 次文本色
@disabled-color : rgba(0, 0, 0, .25); // 失效色
@border-radius-base: 4px; // 組件/浮層圓角
@border-color-base: #d9d9d9; // 邊框色
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, .15); // 浮層陰影
- 如何開啟cssModules
如何開啟cssModules
import React from 'react';
import { Input, Form, Button } from 'antd';
import S from './login.module.scss'; --------------------- 引入
const FormItem = Form.Item;
export default class Login extends React.Component {
render() {
return (
<div className={S.login} > ---------------------------------- 寫成對象的形式
<Form>
<FormItem>
用戶名:<Input></Input>
</FormItem>
<FormItem>
密碼:<Input></Input>
</FormItem>
<FormItem>
<Button type="primary">登陸</Button>
</FormItem>
</Form>
</div>
)
}
}
redux-devtools-extension
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
const totalReducers = {
};
const store = createStore(
combineReducers({
...totalReducers
}),
composeWithDevTools(
applyMiddleware(),
)
);
export default store;
(二) 授權(quán)登陸
(教程)http://www.cftea.com/c/2016/11/6703.asp
(豬八戒授權(quán)文檔)http://open.zbj.com/wiki/getWikiCategoryAll?wikiid=8#header
react-facebook-login 和 react-google-login
<GoogleLogin
clientId="6099641770..................apps.googleusercontent.com"
redirectUri="https://tools............app"
buttonText="LOGIN WITH GOOGLE"
autoLoad={false}
onSuccess={this.responseGoogle}
onFailure={this.responseGoogle}
// accessType="offline"
// uxMode="redirect"
uxMode="popup"
className="google-content"
style={{border: 'none'}}
/>
responseGoogle = async(response) => {
if (response.error) {
// message.error(response.error, 2)
return;
} else {
try {
let accessToken = response.accessToken;
const params = {
acToken: accessToken,
userType: 'STORE',
}
const res = await carbonLoginApi(googleGet(params)); // 用google獲取得token白群,換取本服務(wù)器token
if ( res.status === 200 ) {
const token = res.data.token;
window.localStorage.setItem('token', token);
// const meRes = await carbonLoginApi(profilesGet()); // 請求me接口,看是否需要修改密碼
// if ( meRes.status === 200 ) {
// if (res.data.isNeedModifyPassword) {
// console.log('請重新設(shè)置密碼硬霍,')
// }
// }
this.props.history.push('/request')
}
} catch (err) {
message.error(err.message)
}
}
}
(二) ISO8601標(biāo)準(zhǔn)時間格式 ---- UTC時間帜慢,GMT時間
--------- ISO 8601的標(biāo)準(zhǔn)格式是:YYYY-MM-DDTHH:mm:ss.sssZ
-----------------------------------------: year
-month
-date
Thour
:minute
:second
.millisecond
Z
(1) utc時間
'2018-10-30T12:53:19.000Z'-------------這樣的時間符合iso8601時間標(biāo)準(zhǔn)
T:表示UTC時間,UTC時間又叫世界協(xié)調(diào)時間
Z:表示時區(qū)-----如果沒跟任何數(shù)字表示0時區(qū)( Z:時區(qū)唯卖,可以是:Z(UFC)粱玲、+HH:mm、-HH:mm )
T 也可以用空格表示拜轨,但是這兩種表示有點不一樣抽减,T 其實表示 UTC,而空格會被認(rèn)為是本地時區(qū)(前提是不通過 Z 指定時區(qū))
> new Date('1970-01-01 00:00:00') --------------------- 空格是本地時區(qū)
Thu Jan 01 1970 00:00:00 GMT+0800 (CST)
> new Date('1970-01-01T00:00:00') ---------------------- T是utc時間
Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
(2) gmt時間
'Thu Nov 01 2018 08:58:27 GMT+0800 '
GMT+0800 : 表示東八區(qū)時區(qū)------- new Date()得到的是GTM本地時間
(3) Date對象最重要的幾個方法
Date.prototype.valueOf() ------- 使用時間戳?xí)r橄碾,都用valueOf轉(zhuǎn)成時間戳提交到后端
valueOf方法返回實例對象距離時間零點(1970年1月1日00:00:00 UTC)對應(yīng)的毫秒數(shù)卵沉,
該方法等同于getTime方法。
new Date( new Date().valueOf() )
new Date().valueOf -------------------------- 返回距離時間零點的毫秒數(shù)
返回:1541035593721
new Date( new Date().valueOf() )------------- 返回對應(yīng)的GMT時間
返回:Thu Nov 01 2018 09:27:02 GMT+0800
var d = new Date();
d.valueOf() // 1362790014817
d.getTime() // 1362790014817
Date.prototype.toString() ------- toString方法返回一個完整的日期字符串法牲。
var d = new Date(2013, 0, 1);
d.toString()
// "Tue Jan 01 2013 00:00:00 GMT+0800 (CST)"
d
// "Tue Jan 01 2013 00:00:00 GMT+0800 (CST)"
d 和 d.toString()返回結(jié)果是一樣的史汗,即 new Date()會自動調(diào)用toString()方法
( 因為toString是默認(rèn)的調(diào)用方法,所以如果直接讀取Date實例拒垃,就相當(dāng)于調(diào)用這個方法停撞。 )
Date.prototype.toISOString() ------- 返回對應(yīng)的ISO8601格式的時間字符串
Date.prototype.toJSON() ------------- toJSON方法返回一個符合 JSON 格式的 ISO 日期字符串
toISOString() 和 toJSON()方法返回值是相等的
var d = new Date(2013, 0, 1);
d.toISOString()
// "2012-12-31T16:00:00.000Z"
d.toJSON()
// "2012-12-31T16:00:00.000Z"
moment.js
上周的開始時間UTC時間
const lastWeekStart = moment().subtract(1,"w").startOf('isoWeek').toDate().toJSON();
上周的結(jié)束時間UTC時間
const lastWeekEnd = moment().add(-1,"w").endOf('isoWeek').toDate().toJSON();
上個月的開始時間UTC時間
const lastMonthStart = moment().month(moment().month()-1).startOf('month').utc().format();
上個月的結(jié)束時間UTC時間
const lastMonthEnd = moment().month(moment().month()-1).endOf('month').utc().format();
----------
moment().subtract(Number, String); 減法 ---- 返回的是一個moment對象
moment().subtract(Number, String).toDate() ---- 返回get the native Date object,原時間對象
moment().subtract(Number, String).toISOString() ---- 返回ISO8601格式時間字符串
moment().subtract(1, 'days') === moment.add(-1, 'days') 減一天
moment().startOf('isoWeek'); ----- 返回ISO8601格式的moment對象
--- set to the first day of this week according to ISO 8601, 12:00 am
-----------------------------( isBetween )------------------------------------------------
moment().isBetween(moment-like, moment-like);
moment().isBetween(moment-like, moment-like, String);
// where moment-like is Moment|String|Number|Date|Array
// moment-like可以是一個Moment對象,字符串悼瓮,數(shù)字....
moment('2010-10-20').isBetween('2010-01-01', '2012-01-01', 'year'); // false
moment('2010-10-20').isBetween('2009-12-31', '2012-01-01', 'year'); // true
( isBetween )
A!0怠8惫琛!3嵊?制!!
const todayStart = moment().startOf('day'); -- 返回的是今天的開始時間的moment對象
const todayEnd = moment().endOf('day');
if ( moment(item.lastReplyAt).isBetween(todayStart, todayEnd) ) { -- isBetween
createTime = moment(item.lastReplyAt).format('h:mm a');
} else {
createTime = moment(item.lastReplyAt).format('MM / DD') // 格式化成月/日
}
L酌础E嗉骸!E呙凇J∽伞!g枋摇零蓉!
目錄:
- 數(shù)組(對象)去重
--- (1) 數(shù)組的reduce方法笤受,沒重復(fù)push,重復(fù)不做任何操作
--- (2) lodash庫的_.uniqWith(array, _.isEqual);
- word-break 屬性
- word-wrap 屬性
- white-space 屬性
- text-overflow 屬性
- Element.scrollIntoView
- 嵌套路由,子路由
https://blog.csdn.net/hsany330/article/details/78114805 - componentWillReceiveProps
https://www.cnblogs.com/gdsblog/p/7348375.html
https://blog.csdn.net/huanghanqian/article/details/80721575 - scrollHeight = scrollTop + clientHeight
http://www.reibang.com/p/c14f85f109ee
https://www.jb51.net/article/58688.htm
onScroll事件 和 onWheel事件
8.1 scrollIntoView() ------------- 滾動當(dāng)前元素到瀏覽器的可視區(qū)域
!! scrollIntoView()類似于 window.location.hash
- 滾動平滑css屬性
scroll-behavior: smooth; -- 平滑
el.scrollIntoView(); // 等同于el.scrollIntoView(true)
el.scrollIntoView(false);
方法可以接受一個布爾值作為參數(shù)敌蜂。
如果為true箩兽,表示元素的頂部與當(dāng)前區(qū)域的可見部分的頂部對齊(前提是當(dāng)前區(qū)域可滾動);
如果為false章喉,表示元素的底部與當(dāng)前區(qū)域的可見部分的尾部對齊(前提是當(dāng)前區(qū)域可滾動)汗贫。
如果沒有提供該參數(shù),默認(rèn)為true秸脱。
- 偽元素和偽類
https://www.cnblogs.com/m2maomao/p/7744227.html - 正則對象
- background
background-color
background-image
background-image:url()
background-size -----------B浒!
background-size: cover拉伸圖片摊唇,有可能一部分會超出
bckground-size: contain縮放圖片咐蝇,有可能一部分會出現(xiàn)空白,無法填充滿
http://www.w3school.com.cn/tiy/c.asp?f=css_background-size&p=8
background-position -----------6羝嘹害!
background-position: 第一個參數(shù)是水平位置,第二個參數(shù)垂直位置吮便,如果規(guī)定了一個值笔呀,另一個值是50%
background-position: center center
= background-position: center
是一樣的
background-position: 50% 50%
= 0%表示左上角,100%表示右下角
http://www.w3school.com.cn/cssref/pr_background-position.asp
background-attachment
background-attachment : ( scroll , fixed )
元素內(nèi)背景圖片是否隨元素滾動而移動
https://www.cnblogs.com/rain-null/p/7064136.html
background-repeat
background-origin
background-clip
- 動效(元素底部髓需,從中間向兩邊組件變長的橫線)
html:
<div className="animate">animate test</div>
css:
.animate {
position: relative; // 父元素相對定位许师,!!偽類就當(dāng)前元素的子元素
display: inline-block;
}
.animate::after { // 偽類相當(dāng)于當(dāng)前元素的子元素,只是不在dom中
content:''; // 一定要有內(nèi)容僚匆,否則偽元素不會被撐開
position: absolute;
left:0; // 定位到父元素的底部
bottom:0;
height: 2px;
background: blue;
left: 50%; // left和right都是50%微渠,則偽類被擠壓到寬度是0,看不見了
right: 50%;
transition: all 0.5s;
display: inline-block;
}
.animate:hover::after {
content: '';
position: absolute;
height: 2px;
background: blue;
left: 0;
right: 0; // hove的時候咧擂,還原div的長度逞盆,正好是中間向兩邊擴(kuò)散
display: inline-block;
}
- 全局作用域 , 函數(shù)作用域 ------------------- 鏈?zhǔn)阶饔糜?br>
函數(shù)內(nèi)部可以直接讀取全局變量
函數(shù)外部無法讀取函數(shù)內(nèi)部聲明的變量 - lodash ----------------- isEqual
_.isEqual(value, other) -------- 深度比較值是否相等
*值得類型可以是 數(shù)組松申,對象云芦,等
*值得類型是對象時:不考慮繼承屬性(inherited: inherited是繼承的意思),只比較自身屬性
argument: 需要比較的兩個值
return: 返回一個布爾值
- 函數(shù)
函數(shù)聲明時贸桶,如果使用表達(dá)式賦值給變量的形式舅逸,表達(dá)式后需要加分號,表示語句的結(jié)束皇筛。
- 函數(shù)名視同變量名琉历,存在函數(shù)名提升。(注意:是function關(guān)鍵字聲明的函數(shù)存在函數(shù)名提升,而采用變量賦值聲明的函數(shù)旗笔,不存在函數(shù)名提升彪置,而僅僅是提升變量)
- 不能在 ( if ) 或者 ( try catch) 語句中聲明函數(shù),因為函數(shù)名存在變量提升换团,注意是function關(guān)鍵字聲明的函數(shù)
- 函數(shù)的
name屬性
,length屬性
,toString()方法
- length屬性返回形參的個數(shù)
- 函數(shù)的toString返回函數(shù)的源碼的字符串形式
- 作用域:指變量存在的范圍
- 對于var命令來說悉稠,局部變量只能在函數(shù)內(nèi)部聲明宫蛆,在其他區(qū)塊中聲明的變量艘包,都是全局變量
- 函數(shù)本身也是一個值,也有自己的作用域耀盗,和變量一樣想虎,
函數(shù)的作用域是其聲明時所在的作用域,與其運行時的作用域無關(guān)
- 函數(shù)執(zhí)行時的作用域叛拷,是函數(shù)定義時的作用域舌厨,而不是調(diào)用時的作用域
很容易犯錯的一點是,如果函數(shù)A調(diào)用函數(shù)B忿薇,卻沒考慮到函數(shù)B不會引用函數(shù)A的內(nèi)部變量裙椭。
- 函數(shù)內(nèi)部聲明的函數(shù),作用域綁定在函數(shù)內(nèi)部
- 傳遞方式
1. 傳值傳遞:
函數(shù)的參數(shù)是原始類型的值( 數(shù)字署浩,字符串揉燃,布爾值 ),是傳值傳遞筋栋,在函數(shù)內(nèi)部修改參數(shù)值炊汤,不會影響函數(shù)外部---------------------------- 原始值的拷貝
2. 傳址傳遞:
函數(shù)的參數(shù)是復(fù)合類型的值 (數(shù)組,對象弊攘,其他函數(shù))抢腐,是傳址傳遞,在函數(shù)內(nèi)部修改參數(shù)值襟交,會影響函數(shù)外部---------------------------------- 原始值的地址
3. 注意:
函數(shù)內(nèi)部修改的不是參數(shù)對象的某個屬性迈倍,而是替換掉整個參數(shù),這時不會影響原始值 - IIFE立即執(zhí)行函數(shù)
function關(guān)鍵字出現(xiàn)在行首捣域,一律解析成語句啼染。所以function關(guān)鍵字出現(xiàn)在行首,認(rèn)為是函數(shù)聲明語句竟宋,不該以()圓括號結(jié)尾提完。所以function(){}()會報錯
(function(){}());
或者(function(){})();
----------------------注意分號是必須的
以圓括號開頭,引擎認(rèn)為圓括號后面跟的是表達(dá)式丘侠,就不會報錯
f();
var f = function (){};
---------------------------------- 等同于
var f;
f();
f = function () {};
(1) word-break 屬性
word-break :規(guī)定自動換行的處理方法
- word-break: break-all 允許在單詞內(nèi)換行
- word-break: keep-all 只能在半角空格或連字符處換行徒欣。
( 文字超出自動換行 ) https://blog.csdn.net/ysynhtt/article/details/44301461
( 文字超出自動換行 ) http://www.cnblogs.com/loya1015/p/5992366.html
中文在div中會自動換行,英文和數(shù)字不會蜗字,英文沒空格時會被認(rèn)為是一個單詞打肝,則不會換行
(2) word-wrap 屬性
word-wrap : 允許( 長單詞 )或者( url地址 )換行到下一行
- word-wrap: break-word 在長單詞或 URL 地址內(nèi)部進(jìn)行換行脂新。
對比
word-wrap: break-word ------------------- 整個單詞一起被換行
word-break: break-all ---------------------- 單詞內(nèi)換行,單詞會被分開
(3) white-space 屬性
white-space 設(shè)置如何處理元素內(nèi)的空白
- white-space: nowrap 文本不換行粗梭,文本會在同一行上繼續(xù)争便,直到遇到 br 標(biāo)簽為止
- white-space: pre-wrap 保留空白符序列,但是正常地進(jìn)行換行
- white-space: pre-line 合并空白符序列断医,但是保留換行符
- white-space: inherit 規(guī)定應(yīng)該從父元素繼承 white-space 屬性的值
herit: 是繼承的意思
(4) text-overflow 屬性
text-overflow 文本溢出的css
- text-overflow: ellipsis 顯示省略符號來代表被修剪的文本滞乙。
- text-overflow: string 使用給定的字符串來代表被修剪的文本。
- text-overflow: clip 修剪文本鉴嗤。
clip是修剪得意思
https://blog.csdn.net/lpandeng/article/details/72885811
(顯示x行后斩启,超出顯示...) https://www.cnblogs.com/like-xcm/p/5849630.html
超出設(shè)定大小的div后,文字顯示 省略號
html
<div className="ellipsis">
sfdsdfasfsdfasdf good welllllllllllllllll hao djfksjdkfs fsadfas sdf sdf s df sdf
</div>
css
.ellipsis {
width: 100px;
height: 60px;
background: yellow;
word-break: break-all; // 單詞內(nèi)換行醉锅,會分開單詞
word-wrap: break-word; // 整個單詞都會被換行兔簇,不會被分開
text-overflow: ellipsis; // 文字溢出,顯示省略號
white-space: nowrap; // 不換行
over-flow: hidden; // 這個一定不能忘了硬耍,否則不會顯示省略號
}
(1) 數(shù)組(對象數(shù)組去重)
采用數(shù)組的reduce方法
Array.reduce((累計變量垄琐,當(dāng)前變量,當(dāng)前位置经柴,原數(shù)組) => {...}, 累計變量初始值)狸窘;
Array.reduce((cumulate, current, index) => {...}, initial )
第一個參數(shù)是:函數(shù),該函數(shù)又有4個參數(shù)
第二個參數(shù)是:累計變量的初始值
返回值: 返回值是最后一次的計算結(jié)果?诙Аk啊!
let _arr = [
{id:'1', name:'wang'},
{id:'2', name:'li'},
{id:'3', name:'zhang'},
{id:'4', name:'wu'},
{id:'1', name:'wang'},
];
let _obj = {};
let result = _arr.reduce((cumulate, current) => {
let _radom = _obj[current.id] ? '' : _ojb[current.id] = true && cumulate.push(current);
return cumulate
}, []) // 注意:這里給累計變量的初始值是一個空數(shù)組
// result就是去重后的數(shù)組
解析:
(1) 在react中鹃操,三元表達(dá)式的返回值韭寸,需要賦給一個變量,不然此處會報錯
(2) 計算過程:
_ojb['1']不存在荆隘,就給_ojb['1']賦值為true (其他值也可以)恩伺,并且往空數(shù)組中push對象{id:'1', name:'wang'},
...
...
_ojb['1']存在,則不做任何操作 ------------ 則重復(fù)項椰拒,并沒有push到累計變量數(shù)組中
最后:返回累積變量數(shù)組
--------------------------------------------
lodash
_.uniqWith( 重復(fù)項數(shù)組, _.isEqual) 返回值就是去重的數(shù)組
字符集
javascript使用unicode字符集晶渠,javascript內(nèi)部所有字符都使用unicode表示
base64轉(zhuǎn)碼
javascript原生提供兩個base64相關(guān)方法
- 什么是base64:
base64是一種編碼方法,可以將任意值
轉(zhuǎn)換成0~9燃观, A~Z褒脯, a~z, +缆毁, /
這64
個字符組成的可打印字符 - 作用:
不出現(xiàn)特殊字符番川,和加密 - 使用場景:
- 文本包含一些不可打印的符號, 則可以使用base64編碼,
轉(zhuǎn)成可打印的字符
-
以文本方式轉(zhuǎn)遞二進(jìn)制數(shù)據(jù)
,可以使用base64編碼
btoa():任意值轉(zhuǎn)為 Base64 編碼
atob():Base64 編碼轉(zhuǎn)為原來的值
這兩個字符都不適合非 ASCII的字符
如: btoa('您好')會報錯
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
var x = '中文';
decodeURIComponent(atob(btoa(encodeURIComponent(x)))) // 輸出中文
react-create-app建立的項目把包去掉.map文件
- map文件是幫助我們查看報錯的位置的颁督。
- map文件由devtool屬性控制践啄,如果不想要map,注釋掉就可以沉御,大約webpack.config.prod.js第57行屿讽;
一個完整的url地址
http://localhost:8080/a/b/c?a=1&b=2#abc
window.location
( http://localhost:8080/a/b/c?a=1&b=2#abc )
protocol協(xié)議:-------- 'http:' 注意包括:
hostname域名:-------- 'localhost'
host域名+端口:------- 'localhost:8080' 包括主機(jī)名,":"和端口號
hash:--------------- '#abc' #號開始的url
search:------------- '?a=1&b=2' ?開始的部分
pathname: ------------ '/a/b/c' 當(dāng)前 URL 的路徑部分吠裆,注意以 / 開頭
origin: -------------- 'http://localhost:8080' 返回url中完整的協(xié)議和主機(jī)地址部分,包括端口
herf:---------------- 'http://localhost:8080/a/b/c?a=1&b=2#abc' 完整的url
// query:-------------- 'a=1&b=2' window.location中沒有query屬性
proxy
create-react-app中設(shè)置proxy
https://segmentfault.com/q/1010000008508440/a-1020000008516740
"proxy": "http://image.baidu.com"
getData = async() => {
const res = await axios.
get('/channel/listjson?pn=0&rn=30&tag1=明星&tag2=全部&ie=utf8')
.then(res => console.log(res))
}
說明:
(1) 上面訪問'/channel/listjson?pn=0&rn=30...'將被代理到下面的地址:
---------- "http://image.baidu.com/channel/listjson?pn=0&rn=30..."
(2) 所以在瀏覽器看來訪問的是'/channel/listjson?pn=0&rn=30...' 所以不會有跨域問題
------------
interceptor
axios中的攔截器
You can intercept requests or responses before they are handled by then or catch.
你可以在請求或者響應(yīng)的中伐谈,在then和catch方法前攔截請求
實例:
import axios from 'axios';
import { message } from 'antd';
const isDev = window.location.origin === '............';
const isLocalhost = window.location.origin === '.........................';
export const hostname = isDev || isLocalhost ? '................' : '........................' ;
const _axios = axios.create({
baseURL: hostname,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
_axios.interceptors.request.use(request => { // 請求攔截
const {token} = localStorage;
if (token) {
request.headers.token = token;
}
return request;
}, error => Promise.reject(error) )
_axios.interceptors.response.use(response => { // 響應(yīng)攔截
return response;
}, error => {
if (error.response) {
switch(error.response.status) {
case 401:
{
message.config({
maxCount: 1,
});
message.error('Login expired, please login again');
window.location.href = '#/login';
break;
}
case 500:
{
message.error('Network Error');
break;
}
default:
break;
}
}
return Promise.reject(error)
})
export default _axios;