转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥"前端一万小时"两大明星专栏------"从零基础到轻松就业"、"前端面试刷题",已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
javascript
涉及面试题:
如何发起 AJAX 调用以及应该在哪些组件生命周期方法中进行 AJAX 调用?
编号:[react_26]
1 获取接口的数据
紧接上篇代码,我希望发送一个 AJAX 请求,并将获取到的数据放到 TodoList 列表项里。
🔗前置知识:《React 进阶------⑧ React 生命周期函数(下):巧用 componentDidMount 进行 AJAX 数据请求》
打开 TodoList.js
文件(⚠️注意:我们依然用上边"前置知识"里 RAP2 模拟好的接口!)
jsx
import React, {Component} from "react";
import 'antd/dist/antd.css';
import store from "./store";
import {getInputChangeAction, getAddItemAction, getDeleteItemAction} from "./store/actionCreators";
import TodoListUI from "./TodoListUI";
import axios from "axios"; // 1️⃣首先,引入 axios 模块;
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange);
}
render() {
return(
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleButtonClick={this.handleButtonClick}
handleItemDelete={this.handleItemDelete}
/>
)
}
componentDidMount() { /*
2️⃣然后在 componentDidMount 函数里,
去调用 axios 的相关方法获取数据;
*/
// 3️⃣调用 axios 的 get 方法,去获取模拟接口里的数据;
axios.get("http://rap2api.taobao.org/app/mock/232799/api/todolist")
.then((res) => {
const data = res.data.data; // 4️⃣一旦请求成功,就将 res.data.data 这个"数组"赋值给 data;
})
.catch(() => {alert("error")})
}
handleInputChange(e) {
const action = getInputChangeAction(e.target.value)
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleButtonClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index) {
const action = getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoList;
2 通过 Redux 的工作流程,运用接口返回的数据
5️⃣既然获取到了接口的数据,我们就可以按照 Redux 的工作流程进行一步步操作;
再次打开 TodoList.js
文件;
jsx
import React, {Component} from "react";
import 'antd/dist/antd.css';
import store from "./store";
// 5️⃣-③:引入 initListAction;
import {getInputChangeAction, getAddItemAction, getDeleteItemAction, initListAction} from "./store/actionCreators";
import TodoListUI from "./TodoListUI";
import axios from "axios";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange);
}
render() {
return(
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleButtonClick={this.handleButtonClick}
handleItemDelete={this.handleItemDelete}
/>
)
}
componentDidMount() {
axios.get("http://rap2api.taobao.org/app/mock/232799/api/todolist")
.then((res) => {
const data = res.data.data;
// 5️⃣-①:创建一个 action,让它表示我要做的事;
const action = initListAction(data); /*
5️⃣-②:由于我们采用了 actionCreator
统一创建 action 的方式编写代码,
故这里直接调用 initListAction 函数,
并将获得的"数据"作为"实参"传入;
❗️请一定记得在上边对 initListAction 引入!
*/
})
.catch(() => {alert("error")})
}
handleInputChange(e) {
const action = getInputChangeAction(e.target.value)
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleButtonClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index) {
const action = getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoList;
5️⃣-④:由于我们采用了 actionTypes 的拆分, 故需要在 actionTypes.js
中定义常量 INIT_LIST_ACTION
;
javascript
export const CHANGE_INPUT_VALUE = "change_input_value";
export const ADD_TODO_ITEM = "add_todo_item";
export const DELETE_TODO_ITEM = "delete_todo_item";
// ❗️定义常量 INIT_LIST_ACTION;
export const INIT_LIST_ACTION = "init_list_action";
打开 actionCreators.js
文件:
javascript
// 5️⃣-⑤:引入"常量"INIT_LIST_ACTION;
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION} from "./actionTypes";
export const getInputChangeAction = (value) => ({
type: CHANGE_INPUT_VALUE,
value
});
export const getAddItem = () => ({
type: ADD_TODO_ITEM
});
export const getAddItemAction = () => ({
type: ADD_TODO_ITEM
});
export const getDeleteItemAction = (index) => ({
type: DELETE_TODO_ITEM,
index
})
export const initListAction = (data) => ({ /*
5️⃣-⑥:在 actionCreators.js
里创建一个 initListAction 函数,
这个函数接收一个 data;
*/
type: INIT_LIST_ACTION, /*
5️⃣-⑦:❗️❗️❗️在 React 里,action 需要用"对象"的形式来表示。
里边有一个 type 属性,用它来告诉 store"你要帮我做的事情是什么?";
*/
data // 5️⃣-⑧:将接收到的 data 返回;
})
5️⃣-⑨:在 TodoList.js
文件中,调用 store 的 dispatch
方法,将 action
发送给 store;
jsx
import React, {Component} from "react";
import 'antd/dist/antd.css';
import store from "./store";
import {getInputChangeAction, getAddItemAction, getDeleteItemAction, initListAction} from "./store/actionCreators";
import TodoListUI from "./TodoListUI";
import axios from "axios";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
store.subscribe(this.handleStoreChange);
}
render() {
return(
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleButtonClick={this.handleButtonClick}
handleItemDelete={this.handleItemDelete}
/>
)
}
componentDidMount() {
axios.get("http://rap2api.taobao.org/app/mock/232799/api/todolist")
.then((res) => {
const data = res.data.data;
const action = initListAction(data);
store.dispatch(action); /*
❗️❗️❗️调用 store 的 dispatch 方法,
将 action 发送给 store;
*/
})
.catch(() => {alert("error")})
}
handleInputChange(e) {
const action = getInputChangeAction(e.target.value)
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleButtonClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete(index) {
const action = getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoList;
5️⃣-⑩:store 会自动 地帮我们把 "当前 store 里的数据 previousState
"和"接收到的 action
" 转发给 reducer;
5️⃣-⑪:既然 reducer 拿到了 previousValue
和 action
,接下来 reducer 就需要告诉 store,现在你"新的数据"应该变成什么样子;
打开 reducer.js
文件:
javascript
// 5️⃣-⑫:引入常量 INIT_LIST_ACTION;
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION} from "./actionTypes";
const defaultState = {
inputValue: "",
list: []
};
export default (state = defaultState, action) => {
if(action.type === CHANGE_INPUT_VALUE) {
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
if(action.type === INIT_LIST_ACTION) { /*
5️⃣-⑬:如果 action 的类型是
INIT_LIST_ACTION,就执行下边的代码;
*/
const newState = JSON.parse(JSON.stringify(state)); // 5️⃣-⑭:同理,拷贝一份数据;
newState.list = action.data; // 5️⃣-⑮:使新数据里的 list 等于 action 的 data;
return newState; // 5️⃣-⑯:同理,返回这个新数据。
}
if(action.type === ADD_TODO_ITEM) {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = "";
return newState;
}
if(action.type === DELETE_TODO_ITEM) {
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
return state;
}
返回页面查看(一切正常):
下一篇,我们会在本篇的基础上,通过使用 Redux 中的"中间件"来实现 AJAX 数据请求!
祝好,qdywxs ♥ you!