摘要:為了提高自己的學(xué)習(xí)效率,避免做一些無用的工作,我也決定以后無論是工作還是學(xué)習(xí)一定要養(yǎng)成定時總結(jié)的習(xí)慣,而且也要用文字記錄下來,這樣可以時常復(fù)習(xí),理清邏輯,加深印象。一種解決方法是將對象作為參數(shù),傳入容器組件。
前言
最近一直在學(xué)習(xí)react技術(shù)棧,相關(guān)的理論和概念基本都了解了,之前也用reactjs寫了幾個demo,切身體會到了函數(shù)式編程和組件化開發(fā)的強大之處,但因各種主客觀原因,事后沒有對相關(guān)知識點進(jìn)行梳理和總結(jié),而且工作中也沒用到,導(dǎo)致現(xiàn)在復(fù)習(xí)的時候生疏了,還需要花大部分時間重新理清需求和邏輯,做了很多重復(fù)性的工作,太得不償失了。為了提高自己的學(xué)習(xí)效率,避免做一些無用的工作,我也決定以后(無論是工作還是學(xué)習(xí))一定要養(yǎng)成定時總結(jié)的習(xí)慣,而且也要用文字記錄下來,這樣可以時常復(fù)習(xí),理清邏輯,加深印象。另外,關(guān)于我個人的學(xué)習(xí)總結(jié),如有不對的地方,歡迎批評指正,期待共同提高!不喜勿噴,謝謝!第一章 頁面搭建 目錄結(jié)構(gòu)
├── components | └──app.css//樣式文件 ├── node_modules //依賴包 ├── static //靜態(tài)文件 | └──index.html //入口html文件 | └──bundle.js //編譯后的js文件 ├── index.js //主入口js文件 ├── package.json //項目所依賴的npm包 ├── webpack.config.js //webpack配置文件 └── yarn.lock //依賴或者更新包相關(guān)版本信息。這樣可以解決同一個項目在不同機(jī)器上環(huán)境不一致的問題。包管理文件 package.json
{ "name": "todolist", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "start": "webpack-dev-server --line --hot", "test": "echo "Error: no test specified" && exit 1" }, "author": "www.icrazyman.cn", "license": "ISC", "devDependencies": { "babel-core": "^6.21.0", "babel-loader": "^6.2.10", "babel-preset-es2015": "^6.18.0", "babel-preset-react": "^6.16.0", "css-loader": "^0.28.4", "react": "^15.4.1", "react-dom": "^15.4.1", "style-loader": "^0.18.2", "webpack": "^1.14.0", "webpack-dev-server": "^1.16.2" }, "dependencies": { "node": "^6.11.1" } }入口文件index.html
index.jsRedux Todos Example
import第三方依賴包和css文件
import React from "react" import { render } from "react-dom" import "./components/app.css" render( , document.getElementById("root") )webpack配置文件webpack.config.js
module.exports = { devtool: "eval-source-map", //選擇map來增強調(diào)試過程 entry: __dirname + "/index.js", //入口文件 output: { path: __dirname + "/static",//打包生成路徑 filename: "bundle.js" }, module: { loaders: [{ test: /.js$/, exclude: /node_modules/, loader: "babel", query: { presets: ["es2015", "react"] } }, { test: /.css$/, loader: "style-loader!css-loader" }] }, devServer: { //熱更新 contentBase: "./static", historyApiFallback: true, inline: true, hot: true } }打開終端運行yarn或npm install安裝依賴,運行npm run build編譯,運行npm start進(jìn)行查看頁面是否正常顯示
小結(jié):這個階段只是把頁面實現(xiàn)出來了,還沒有實現(xiàn)任何邏輯。其中頁面實現(xiàn)的步驟為:
1. 在index.html編寫html結(jié)構(gòu)和css樣式 2. 把html結(jié)構(gòu)提取到index.js組件中同時轉(zhuǎn)換成jsx語法 3. 把css樣式提取到app.css中第二章 引入redux組件化 目錄結(jié)構(gòu)
├── actions | └──index.js//管理狀態(tài) ├── components | └──app.css//樣式文件 | └──App.js//UI組件入口文件 | └──Link.js//UI組件 | └──Todo.js//UI組件 | └──Top.js//UI組件 ├── containers | └──VisibleTodoList.js//容器組件 | └──AddTodo.js//容器組件 | └──FilterLink.js//容器組件 ├── reducers | └──index.js//數(shù)據(jù)邏輯處理文件 ├── node_modules //依賴包 ├── static //靜態(tài)文件 | └──index.html //入口html文件 | └──bundle.js //編譯后的js文件 ├── index.js //主入口js文件 ├── package.json //項目所依賴的npm包 ├── webpack.config.js //webpack配置文件 └── yarn.lock //依賴或者更新包相關(guān)版本信息。這樣可以解決同一個項目在不同機(jī)器上環(huán)境不一致的問題。安裝依賴包
此次新增react-redux和redux依賴包
{ "name": "todolist", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "webpack", "start": "webpack-dev-server --line --hot", "test": "echo "Error: no test specified" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.21.0", "babel-loader": "^6.2.10", "babel-preset-es2015": "^6.18.0", "babel-preset-react": "^6.16.0", "css-loader": "^0.28.4", "react": "^15.4.1", "react-dom": "^15.4.1", "react-redux": "^5.0.1", "redux": "^3.6.0", "style-loader": "^0.18.2", "webpack": "^1.14.0", "webpack-dev-server": "^1.16.2" }, "dependencies": { "node": "^6.11.1" } }index.js
此次利用redux管理整個項目的狀態(tài),并且把項目代碼抽離成組件
//注意:import后不加{}代表引入的default,加了{(lán)}代表引入其中導(dǎo)出的一部分,用到了ES6的解構(gòu) //注意:import后不加{}代表引入的default,加了{(lán)}代表引入其中導(dǎo)出的一部分,用到了ES6的解構(gòu) import React from "react" import { render } from "react-dom" import { Provider } from "react-redux" import { createStore } from "redux" //數(shù)據(jù)邏輯處理保存在reducers里 import todoApp from "./reducers" import App from "./components/App" //在頂層創(chuàng)建store管理整個項目的數(shù)據(jù) const store = createStore(todoApp) console.log("9. root index start") //connect方法生成容器組件以后,需要讓容器組件拿到state對象,才能生成 UI 組件的參數(shù)。 // 一種解決方法是將state對象作為參數(shù),傳入容器組件。但是,這樣做比較麻煩,尤其是容器組件可能在很深的層級,一級級將state傳下去就很麻煩。 // React-Redux 提供Provider組件,可以讓容器組件拿到state。 //Provider在根組件外面包了一層,這樣一來,App的所有子組件就默認(rèn)都可以拿到state了。 render(reducers/index.js,document.getElementById("root") ) console.log("9. root index end")
把數(shù)據(jù)邏輯處理的代碼抽離成reducers
import { combineReducers } from "redux" console.log("data flow:") console.log("1. reducers start") /* 傳入舊的state和作用的action返回一個新state */ const todo = (state, action) => { console.log("data flow 4") switch(action.type) { case "ADD_TODO": return { id: action.id, text: action.text, completed: false //新增默認(rèn)為未完成 } case "TOGGLE_TODO": if (state.id !== action.id) { return state } return Object.assign({}, state, {completed: !state.completed}) default: return state } } const todos = (state = [], action) => { console.log("1.1 todos twice") switch(action.type) { case "ADD_TODO": return [ ...state, todo(undefined, action) ] //todo(undefined, action) 新增一條記錄時第一個參數(shù)state不存在 case "TOGGLE_TODO": return state.map(t => todo(t, action)); default: return state; } } const visibilityFilter = (state = "SHOW_ALL", action) => { console.log("1.2 visibilityFilter twice") switch (action.type) { case "SET_VISIBILITY": return action.filter; default: return state; } } console.log("1. reducers end") export default combineReducers({ todos, visibilityFilter });actions/index.js
在redux中,actions是觸發(fā)store中數(shù)據(jù)更新的唯一來源,所以要寫個actions利用dispatch方法來觸發(fā)store中管理的狀態(tài)更新
let nextTodoId = 0; console.log("2. actions start") // 添加 const addTodo = (text) => { // console.log("text:" + text) console.log("data flow 2") let id = nextTodoId ++ ; return { type: "ADD_TODO", id: id, text } } // 頂部顯示狀態(tài) const setVisibility = (filter) => { // console.log("filter:" + filter) return { type: "SET_VISIBILITY", filter } } // 觸發(fā) const toggleTodo = (id) => { // console.log("id:" + id) return { type: "TOGGLE_TODO", id } } export {addTodo, setVisibility, toggleTodo} console.log("2. actions end")components/App.js
子組件的入口文件,負(fù)責(zé)對抽離出的子組件進(jìn)行組合然后導(dǎo)出
import React from "react" import Top from "./Top" import VisibleTodoList from "../containers/VisibleTodoList" import AddTodo from "../containers/AddTodo" import "./app.css" console.log("8. App.js start") const App = () => (components/Top.js) console.log("8. App.js end") export default App;
TodoList頂部組件
import React from "react" import { connect } from "react-redux" import { setVisibility } from "../actions" import FilterLink from "../containers/FilterLink" console.log("4. Top.js start") const Top = () => (containers/FilterLink.js); console.log("4. Top.js end") export default Top;全部任務(wù) 待辦任務(wù) 已完成任務(wù)
過濾組件
import React from "react" import { connect } from "react-redux" import { setVisibility } from "../actions" import Link from "../components/Link" //第二個參數(shù)表示組件自身的props //mapStateToProps()將state節(jié)點注入到與view相關(guān)的組件 const mapStateToProps = (state, ownProps) => { // console.log({state,ownProps}) return { active: ownProps.filter === state.visibilityFilter } } //mapDispatchToProps()將需要綁定的響應(yīng)事件注入到組件上 const mapDispatchToProps = (dispatch, ownProps) => { return { onClick: () => { dispatch(setVisibility(ownProps.filter)) } } } //connent()函數(shù)生成容器組件 const FilterLink = connect( mapStateToProps, mapDispatchToProps )(Link) export default FilterLink;components/Link.js
展示組件,顯示頂部狀態(tài)按鈕
import React from "react"; console.log("3. Link.js start") const Link = ({ active, children, onClick }) => { return ( ) } console.log("3. Link.js end") export default Link;components/Todo.js
每一個Todo子組件
import React from "react" console.log("5. Todo.js start") //UI 組件有以下幾個特征。 // 只負(fù)責(zé) UI 的呈現(xiàn),不帶有任何業(yè)務(wù)邏輯 // 沒有狀態(tài)(即不使用this.state這個變量) // 所有數(shù)據(jù)都由參數(shù)(this.props)提供 // 不使用任何 Redux 的 API // UI 組件又稱為"純組件",不含狀態(tài),純粹由參數(shù)決定它的值 const Todo = ({ onClick, completed, text }) => (
TodoList列表組件
import React from "react" import Todo from "../components/Todo" import { connect } from "react-redux" import { toggleTodo } from "../actions" console.log("6. VisibleTodoList start") //負(fù)責(zé)管理數(shù)據(jù)和業(yè)務(wù)邏輯,不負(fù)責(zé) UI 的呈現(xiàn) // 帶有內(nèi)部狀態(tài) // 使用 Redux 的 API const getVisibleTodos = (todos, filter) => { console.log("9.2 getVisibleTodos") switch (filter) { case "SHOW_ALL": return todos; case "SHOW_COMPLETED": return todos.filter(t => t.completed === true)//已完成 case "SHOW_ACTIVE": return todos.filter(t => t.completed === false)//未完成 default: throw new Error("Unknown filter: " + filter) } } //合并redux的狀態(tài)到react的props中 //將state映射到 UI 組件的參數(shù)(props) //mapStateToProps會訂閱 Store,每當(dāng)state更新的時候,就會自動執(zhí)行,重新計算 UI 組件的參數(shù),從而觸發(fā) UI 組件的重新渲染。 //mapStateToProps的第一個參數(shù)總是state對象,還可以使用第二個參數(shù),代表容器組件的props對象。 //使用ownProps作為參數(shù)后,如果容器組件的參數(shù)發(fā)生變化,也會引發(fā) UI 組件重新渲染。 const mapStateToProps = (state, ownProps) => { console.log("9.1 mapStateToProps") // console.log(ownProps) // console.log(state) return { todos: getVisibleTodos(state.todos, state.visibilityFilter) } } //將用戶對 UI 組件的操作映射成 Action //建立 UI 組件的參數(shù)到store.dispatch方法的映射。也就是說,它定義了哪些用戶的操作應(yīng)該當(dāng)作 Action,傳給 Store。它可以是一個函數(shù),也可以是一個對象 //如果mapDispatchToProps是一個函數(shù),會得到dispatch和ownProps(容器組件的props對象)兩個參數(shù)。 //mapDispatchToProps作為函數(shù),應(yīng)該返回一個對象,該對象的每個鍵值對都是一個映射,定義了 UI 組件的參數(shù)怎樣發(fā)出 Action。 //如果mapDispatchToProps是一個對象,它的每個鍵名也是對應(yīng) UI 組件的同名參數(shù),鍵值應(yīng)該是一個函數(shù),會被當(dāng)作 Action creator ,返回的 Action 會由 Redux 自動發(fā)出。 const mapDispatchToProps = (dispatch) => { return { onTodoClick: (id) => { // console.log(id) dispatch(toggleTodo(id)) } } } const TodoList = ({ todos, onTodoClick }) => { console.log("9.3 TodoList") // console.log(todos);//todos數(shù)組 return (
添加Todo子組件
import React from "react" import { connect } from "react-redux" import { addTodo } from "../actions" console.log("7. AddTodo.js start") let AddTodo = ({ dispatch }) => { let input; return (打開終端運行yarn或npm install安裝依賴,運行npm run build編譯,運行npm start進(jìn)行查看頁面和功能是否正常) } AddTodo = connect()(AddTodo)//把addTodo用redux的connect方法重新包裝一下,使其可使用state中的數(shù)據(jù) console.log("7. AddTodo.js end") export default AddTodo;
小結(jié):這個階段把頁面和功能實現(xiàn)出來了,初步把整個項目抽離成組件,也利用redux把代碼業(yè)務(wù)邏輯處理、狀態(tài)管理和狀態(tài)分發(fā)管理分離出來了
總結(jié):本次todolist的項目因時間關(guān)系中間斷了兩次,也算是“因禍得福”吧!我也把這個項目完整地復(fù)習(xí)了一遍。這個項目主要把redux的運用以及數(shù)據(jù)流了解了下,算是大概清楚怎么玩了,為什么說大概呢?一個是因為目前工作中沒有使用,無法運用到實際項目中,一個就是最外層的index.js,不明白為什么console.log是最后打印出來的,也就意味這是最后加載這個文件的,這個文件我的理解不應(yīng)該是整個項目js的主入口文件嗎?為什么反而最后加載呢?不明白,先記下來吧,等以后用到redux了再有意識地研究一下?,F(xiàn)在把自己做這個項目的詳細(xì)步驟、個人理解以及查閱相關(guān)的資料整理出來了,不一定十分準(zhǔn)確,如果有哪位大神有不同的意見歡迎批評指正!最新了解了react,很喜歡它的組件化開發(fā),奈何公司用的卻是JQ,所以在react里我其實還只是個新手,不喜勿噴??!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94814.html
摘要:二基礎(chǔ)就是一個普通的。其他屬性用來傳遞此次操作所需傳遞的數(shù)據(jù),對此不作限制,但是在設(shè)計時可以參照標(biāo)準(zhǔn)。對于異步操作則將其放到了這個步驟為添加一個變化監(jiān)聽器,每當(dāng)?shù)臅r候就會執(zhí)行,你可以在回調(diào)函數(shù)中使用來得到當(dāng)前的。 注:這篇是16年10月的文章,搬運自本人 blog...https://github.com/BuptStEve/... 零、環(huán)境搭建 參考資料 英文原版文檔 中文文檔 墻...
摘要:框架的使用詳解及教程在前段時間,我們也學(xué)習(xí)講解過框架的基本使用,但是有很多同學(xué)在交流群里給我的反饋信息說,框架理解上有難度,看了之后還是一臉懵逼不知道如何下手,很多同學(xué)就轉(zhuǎn)向選擇使用框架。 dva框架的使用詳解及Demo教程 在前段時間,我們也學(xué)習(xí)講解過Redux框架的基本使用,但是有很多同學(xué)在交流群里給我的反饋信息說,redux框架理解上有難度,看了之后還是一臉懵逼不知道如何下手,很...
摘要:而函數(shù)式編程就不一樣了,這是模仿我們?nèi)祟惖乃季S方式發(fā)明出來的。數(shù)據(jù)流在中,數(shù)據(jù)的流動是單向的,即從父節(jié)點傳遞到子節(jié)點。數(shù)據(jù)流嚴(yán)格的單向數(shù)據(jù)流是架構(gòu)的設(shè)計核心。 前言 總括: 本文采用react+redux+react-router+less+es6+webpack,以實現(xiàn)一個簡易備忘錄(todolist)為例盡可能全面的講述使用react全家桶實現(xiàn)一個完整應(yīng)用的過程。 代碼地址:Re...
摘要:首先聲明這篇文章是想說明一下最新版本的的新特性帶來的極大的開發(fā)體驗提升而不是如何利用開發(fā)應(yīng)用這個特性就是對的支持在的中有說明具體可以參考這里在版本之前我們在開發(fā)應(yīng)用尤其是在配合一類庫的時候經(jīng)常用到諸如之類的封裝而這些函數(shù)其實都可以用裝飾器的 首先聲明, 這篇文章是想說明一下最新版本的 TypeScript(3.0) 的新特性帶來的極大的 React 開發(fā)體驗提升. 而不是如何利用 Ty...
摘要:是流行的框架之一,在年及以后將會更加流行。于年首次發(fā)布,多年來廣受歡迎。下面是另一個名為的高階函數(shù)示例,該函數(shù)接受另外兩個函數(shù),分別是和。將所有較小的函數(shù)組合成更大的函數(shù),最終,得到一個應(yīng)用程序,這稱為組合。 React是流行的javascript框架之一,在2019年及以后將會更加流行。React于2013年首次發(fā)布,多年來廣受歡迎。它是一個聲明性的、基于組件的、用于構(gòu)建用戶界面的高...
閱讀 1793·2023-04-26 01:44
閱讀 1219·2021-11-12 10:34
閱讀 1603·2021-09-09 09:33
閱讀 1738·2019-08-30 15:44
閱讀 2899·2019-08-30 13:49
閱讀 2196·2019-08-29 15:26
閱讀 951·2019-08-26 13:30
閱讀 1417·2019-08-23 18:15