#### 各大框架里面的核心內容
**vue**
* vue-cli 3.0 (2.0向3.0的過渡)
* 配置
* 優化
* vue基礎知識
* 雙向數據綁定
* template模板渲染語法和原理(vue-loader 、 虛擬DOM)
* 指令和自定義指令
* methods computed watch filters
* class / style
* 條件和循環渲染
* 事件處理
* 表單處理
* 組件(屬性)
* ref
* 生命周期
* 插槽
* transition
* 渲染函數和jsx
* 插件編寫
* 混入
* devtools
* ……
* vue-router
* 基礎知識
* 動態路由
* 編程式導航
* 命名路由和命名容器
* 導航守衛
* HASH和BROWSER路由
* 路由原理
* ……
* vuex
* state
* getter
* mutation
* action
* module
* mapXxx
* 實現原理
* ……
* 單元測試
* SSR服務器渲染 nuxt.js
* UI組件庫
* ……
**react**
* create-react-app
* 配置
* 優化
* react基礎
* JSX語法(虛擬DOM)
* 狀態
* 屬性
* ref
* 組件
* 生命周期
* PureComponent
* Hooks
* ……
* react-router-dom
* redux
* redux
* react-redux
* 中間件
* ……
* dva
* umi
* typescript
* UI組件
* SSR服務器渲染 next.js
* ……
第二天作業講解
~~~
// TO-STRING
/* var a = {
i: 0,
toString() { //或者valueOf
return ++this.i;
}
};
if (a == 1 && a == 2 && a == 3) {
console.log('條件成立');
} */
/* var a = [1, 2, 3];
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log('條件成立');
} */
/* 數據劫持實現 */
/* var i = 0;
Object.defineProperty(window, 'a', {
get() {
return ++i;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('條件成立');
} */
/* var a = 0;
Object.defineProperty(window, 'a', {
get() {
// Uncaught TypeError: Cannot redefine property: a
// defineProperty GETER攔截器中不能再次獲取當前屬性
return ++a;
}
});
console.log(a); */
~~~
==
1、對象和字符串,對象轉為字符串;
2、null和undefined相等,和其他都不等;
3、NaN和任何都不相等,包含和自己不相等;
4、剩下的都轉為數字;
## 1. Vue2.0/3.0雙向數據綁定的實現原理
~~~
ES5:Object.defineProperty
<body>
姓名:<span id="spanName"></span>
<br>
<input type="text" id="inpName">
<!-- IMPORT JS -->
<script>
let obj = {
name: ''
};
let newObj = {
...obj
};
// let newObj = JSON.parse(JSON.stringify(obj));
Object.defineProperty(obj, 'name', {
get() {
return newObj.name;
},
set(val) {
newObj.name = val;
observe();
}
});
function observe() {
spanName.innerHTML = newObj.name;
}
inpName.oninput = function () {
obj.name = this.value;
};
</script>
</body>
~~~
~~~
/* let obj = {
name: ''
};
let newObj = JSON.parse(JSON.stringify(obj));
Object.defineProperty(obj, 'name', {
get() {
return newObj.name;
},
set(val) {
if (val === newObj.name) return;
newObj.name = val;
observer();
}
});
function observer() {
spanName.innerHTML = obj.name;
inpName.value = obj.name;
}
setTimeout(() => {
obj.name = "珠峰培訓";
}, 1000);
inpName.oninput = function () {
obj.name = this.value;
}; */
/*
* 1. 對原始數據克隆
* 2. 需要分別給對象中而定每一個屬性設置監聽
*/
~~~
~~~
let obj = {};
obj = new Proxy(obj, {
get(target, prop) {
return target[prop];
},
set(target, prop, value) {
target[prop] = value;
observer();
}
});
function observer() {
spanName.innerHTML = obj.name;
inpName.value = obj.name;
}
setTimeout(() => {
obj.name = "珠峰培訓";
}, 1000);
inpName.oninput = function () {
obj.name = this.value;
};
~~~
## 2. MVC和MVVM的區別


~~~
import React from 'react';
import ReactDOM from 'react-dom';
import axios from './axios';
class A extends React.Component {
state = {
name: ''
};
render() {
let { name } = this.state;
return <>
姓名:<span>{name}</span>
<br />
<input type="text" value={name} onChange={ev => {
this.setState({
name: ev.target.value
});
}} />
</>;
}
async componentDidMount() {
setTimeout(_ => {
this.setState({
name: '珠峰培訓'
});
}, 1000);
let data = await axios.get('/product/banner');
console.log(data);
}
}
ReactDOM.render(<>
<A />
</>, document.getElementById('root'));
~~~
## 3\. 跨域問題的解決方案和實現原理
**跨域問題的產生及其價值意義**
前后端分離導致出現跨域
**JSONP跨域解決方案的底層原理** 只能get請求,不安全
客戶端

~~~javascript
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
$.ajax({
url: 'http://127.0.0.1:8001/list',
method: 'get',
dataType: 'jsonp',
success: res => {
console.log(res);
}
});
</script>
~~~
后臺
~~~javascript
let express = require('express'),
app = express();
app.listen(8001, _ => {
console.log('OK!');
});
app.get('/list', (req, res) => {
let {
callback = Function.prototype
} = req.query;
let data = {
code: 0,
message: '珠峰培訓'
};
res.send(`${callback}(${JSON.stringify(data)})`);
});
~~~
**基于iframe的跨域解決方案**
* window.name
* document.domin
* location.hash
* post message
**CORS跨域資源共享**
客戶端
~~~javascript
import axios from 'axios';
import qs from 'qs';
axios.defaults.baseURL = "http://127.0.0.1:3000";
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true;
/*
* 設置請求傳遞數據的格式(看服務器要求什么格式)
* x-www-form-urlencoded
*/
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.transformRequest = data => qs.stringify(data);
/*
* 設置請求攔截器
* TOKEN校驗(JWT):接收服務器返回的token,存儲到vuex/本地存儲中,每一次向服務器發請求,我們應該把token帶上
*/
axios.interceptors.request.use(config => {
let token = localStorage.getItem('token');
token && (config.headers.Authorization = token);
return config;
}, error => {
return Promise.reject(error);
});
/*
* 響應攔截器
*/
axios.interceptors.response.use(response => {
return response.data;
}, error => {});
export default axios;
~~~
服務器端
~~~javascript
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "";
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "PUT,POST,GET,DELETE,OPTIONS,HEAD");
res.header("Access-Control-Allow-Methods", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");
req.method === 'OPTIONS' ? res.send('CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!') : next();
});
~~~
**基于http proxy實現跨域請求**
webpack 在package.js中有proxy:"http://127.0.0.1:9999"
開發的時候用這個,但是服務器還要nginx反向代理
**nginx反向代理**
4.Vue/React框架中關于組件信息通信引發的面試題
* vue
屬性傳遞
發布訂閱(EventBus):$on / $emit
Provide / inject
slot
$parent / $children
vuex
* react
屬性
發布訂閱
React.createContext
redux / react-redux / mobix / dva
本地存儲,redux存在虛擬內存中了,redux不光能狀態管理,還能存儲數據。
> 服務器設置session,服務器返回給客戶端的信息,在響應頭中帶著set-cookie = ‘connect.sid’ 客戶端會把信息種植到本地的cookie中的HTTPonly,客戶端再次向服務器發送請求的時候,會默認在請求頭中cookie把connect.sid傳遞發給服務器。

