React JS Tutorials for Beginners - 1 - Getting Started https://www.youtube.com/watch?v=-AbaV3nrw6E&list=PL6gx4Cwl9DGBuKtLgPR_zWYnrwv-JllpA Downloads: https://facebook.github.io/react/downloads.html Sample code:https://github.com/buckyroberts/React-Boilerplate browser.min.js: Convert jsx into javascript, jsx轉換網站https://babeljs.io/repl/ React JS Tutorials for Beginners - 2 - Simple Demo https://www.youtube.com/watch?v=2NLgQMs2hOw&index=2&list=PL6gx4Cwl9DGBuKtLgPR_zWYnrwv-JllpA Sample Demo: <div id="example"></div> <script type="text/babel"> //注意是txt/babel ReactDOM.render(<h1>Hello World</h1>,document.getElementById('example')); //將Html代碼填充到指定的div中 </script> 3. Components: <div id="example"></div> <script type="text/babel"> var Bacon=React.createClass({ //createClass建立component render: function(){ return (<div> //只能返回一個父元素 <h2>This is a simple component!</h2> <p>This is a simple component!</p> </div> ); } }); ReactDOM.render(<Bacon />,document.getElementById('example')); //ReactDOM.render(<div><Bacon /><Bacon /><Bacon /></div>,document.getElementById('example')); //呈現多個Component </script> 4. Props (Property) <div id="app"></div> <script type="text/babel"> var Movie=React.createClass({ //createClass建立component render: function(){ return (<div> <h1>{this.props.title}</h1> <h2>{this.props.genre}</h2> </div> ); } }); //ReactDOM.render(<Movie />,document.getElementById('app')); ReactDOM.render(<div> <Movie title="Avatar" genre="action" /> <Movie title="The Notebook" genre="romance" /> <Movie title="Captain America" genre="action" /> </div>,document.getElementById('app')); //呈現多個Component </script> 5. Event Handling <div id="container"></div> <script type="text/babel"> var Comment=React.createClass({ //createClass建立component edit: function(){ alert("edit"); }, remove: function(){ alert("remove"); }, render: function(){ return (<div className="commentContainer"> //注意是className <div className="commentText">{this.props.children}</div> //this.props.children顯示下面<Comment></Comment>之間的內容 <button onClick={this.edit} className="button-primary">Edit</button> //事件處理onClick={this.edit} <button onClick={this.remove} className="button-danger">Remove</button> </div> ); } }); ReactDOM.render(<div className="board"> <Comment>Hey my name is Steve</Comment> <Comment>Jack</Comment> <Comment>Amy</Comment> </div>,document.getElementById('container')); </script> 6. State <div id="container"></div> <script type="text/babel"> var Checkbox=React.createClass({ //createClass建立component getInitialState: function(){ //getInitialState設置初始狀態 return {checked:ture} }, handleChecked: function(){ this.setState({checked: !this.state.checked}); //setState設置狀態 }, render:function(){ var msg; if(this.state.checked){ msg="checked" }else{ msg="unchecked" } return (<div> <input type='checkbox' onChange={this.handleChecked} defaultChecked={this.state.checked} /> ////defaultChecked綁定初始狀態 <h2>Checkbox is {msg}</h2> </div>); } }); ReactDOM.render(<Checkbox />,document.getElementById('container')); </script> 7. Adding State to Components <div id="container"></div> <script type="text/babel"> var Comment=React.createClass({ //createClass建立component getInitialState: function(){ return {editing:false} //編輯狀態爲false }, edit: function(){ this.setState({editing:true}); //設置編輯狀態爲true }, remove: function(){ alert("remove"); }, save: function(){ var val=this.refs.newText.value; //用ref來獲取輸入框中的值 this.setState({editing:false}); }, renderNormal: function(){ return (<div className="commentContainer"> <div className="commentText">{this.props.children}</div> <button onClick={this.edit} className="button-primary">Edit</button> <button onClick={this.remove} className="button-danger">Remove</button> </div> ); }, renderForm: function(){ return (<div className="commentContainer"> <textare ref="newText" defaultValue={this.props.children}></textare> //注意defaultValue, 若是給id會致使不少重名,用ref來獲取輸入框中的值 <button onClick={this.save} className="button-success">Save</button> </div> ); }, render: function(){ if(this.state.editing){ return this.renderForm(); }else{ return this.renderNormal(); } } }); ReactDOM.render(<div className="board"> <Comment>Hey my name is Steve</Comment> <Comment>Jack</Comment> <Comment>Amy</Comment> </div>,document.getElementById('container')); </script> 8. Multiple Child Components (在一個容器內排序多個Components) <div id="container"></div> <script type="text/babel"> var Comment=React.createClass({ getInitialState: function(){ return {editing:false} //編輯狀態爲false }, edit: function(){ this.setState({editing:true}); //設置編輯狀態爲true }, remove:function(){ this.props.deleteFromBoard(this.props.index); //調用外層屬性deleteFromBoard } save: function(){ var val=this.refs.newText.value; //用ref來獲取輸入框中的值 this.props.updateCommentText(val,this.props.index); //調用外層屬性updateCommentText this.setState({editing:false}); }, renderNormal: function(){ return (<div className="commentContainer"> <div className="commentText">{this.props.children}</div> <button onClick={this.edit} className="button-primary">Edit</button> <button onClick={this.remove} className="button-danger">Remove</button> </div> ); }, renderForm: function(){ return (<div className="commentContainer"> <textare ref="newText" defaultValue={this.props.children}></textare> //注意defaultValue, 若是給id會致使不少重名,用ref來獲取輸入框中的值 <button onClick={this.save} className="button-success">Save</button> </div> ); }, render: function(){ if(this.state.editing){ return this.renderForm(); }else{ return this.renderNormal(); } } }); var Board=React.createClass({ //Comment是組件,組件能夠有不少個.Board是組件外面的容器用於管理裏面的多個組件. getInitialState:function(){ return{ comments:[ 'aaaaaa', 'bbbbbb', 'cccccc' ] } }, add:function(text){ var arr=this.state.comments; arr.push(text); //push,把元素加入數組 this.setState({comments:arr}); }, removeComment: function(i){ var arr=this.state.comments; arr.splice(i,1); //從第i個開始,去掉1個元素.返回新的數組. this.setState({comments:arr}); }, updateCommand:function(newText,i){ var arr=this.state.comments; arr[i]=newText; //將新值賦值給數組中指定的元素 this.setState({comments:arr}); //更新數組,將新數組arr更新到comments中 } eachComment:function(text,i){ return ( <Comment key={i} index={i} updateCommentText={this.updateComment} deleteFromBoard={this.removeComment}> //注意關鍵字 key和index, 以及自定義屬性updateCommentText,deleteFromBoard {text} </Comment> ); }, render:function(){ return( <div> <button onClick={this.add.bind{null,'some default text'}} className="button-info Create">Add New</button> //注意寫法onClick={this.add.bind{null,'some default text'}} <div className="board"> { this.state.comments.map(this.eachComment) //map至關於for循環 } </div> </div> ); }; }); ReactDOM.render(<Board />,document.getElementById('container')); </script> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- constructor(){ super(); this.state={name: "Will"}; } this.setState({name:"Bob"}); changeTitle={this.changeTitle.bind(this)} //changeTitle方法在當前js文件中須要用.bind(this) REACT JS TUTORIAL #6 - React Router & Intro to Single Page Apps with React JS https://www.youtube.com/watch?v=1iAG6h9ff5s&index=6&list=PLoYCgNOIyGABj2GQSlDRjgvXtqfDxKm5b Bootstrap模版: startbootstrap.com 安裝react router的命令: npm install -S react-router Store相似於Angularjs中的Service. componentWillMount(){//Component的構造函數 TodoStore.on("change",this.getTodos); } componentWillUnmount(){ //必須卸載這個方法,否則會致使內存泄露. TodoStore.removeListener("change",this.getTodos); } npm install -S flux Actions -> Dispatcher -> Stores -> Components -> Actions. import * as TodoAcions from "../action/TodoAcions"; //表示TodoActions中的全部方法. Ajax: axios("http://someurl.com/somedataendpoint").then((data)=>{ console.log("got the data!",data); }); Redux核心概念有三個:actions,store,reducers. Immutable JS - Redux Tutorial #2 - React.js Tutorial https://www.youtube.com/watch?v=9M-r8p9ey8U&list=PLoYCgNOIyGABj2GQSlDRjgvXtqfDxKm5b&index=16 var a={name:"Will", things:[0,1,2]} var b=Object.assign({},a,{name:"Fred"}) b.things=a.things.concat(3) state={...state,age:action.payload} Redux Middleware Tutorial - Redux Tutorial #5 https://www.youtube.com/watch?v=DJ8fR0mZM44&list=PLoYCgNOIyGABj2GQSlDRjgvXtqfDxKm5b&index=19 中間件: import {applyMiddleware,createStore} from "redux"; const logger=(store)=>(next)=>(action)=>{ console.log("action fired",action); next(action); } const store=createStore(reducer,1,middleware) Connecting React & Redux - Redux Tutorial #7 https://www.youtube.com/watch?v=nrg7zhgJd4w&index=21&list=PLoYCgNOIyGABj2GQSlDRjgvXtqfDxKm5b import {connect} from "react-redux" @connect((store)=>{ return{ user:store.user.user, userFetched:store.user.fetched, tweets:store.tweets.tweets, }; }) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ReactJS / Redux Tutorial - #1 Introduction https://www.youtube.com/watch?v=qrsle5quS7A&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ npm install redux -save //安裝redux js中的對象: const initialState = { result:1, lastValues:[] } state = { ...state, //ES6語法,包括state對象的全部屬性 result: state.result + action.payload, lastValues: [...state.lastValues,action.payload] } ReactJS / Redux Tutorial - #5 Multiple Reducers https://www.youtube.com/watch?v=BVvBa18o8Es&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=5 import {createStore, combineReducers} from "redux" const store = createStore(combineReducers({mathReducer,userReducer})); ReactJS / Redux Tutorial - #6 Redux Middleware https://www.youtube.com/watch?v=AgO7YcJeBh4&index=6&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ import {createStore, combineReducers, applyMiddleware} from "redux" const myLogger = (store) => (next) => (action) => { console.log("Logged Action",action); next(action); } const store = createStore(combineReducers({mathReducer,userReducer}), {}, applyMiddleware(myLogger)); npm install redux-logger --save import logger from "redux-logger"; const store = createStore(combineReducers({mathReducer,userReducer}), {}, applyMiddleware(logger())); ReactJS / Redux Tutorial - #7 Connect ReactJS and Redux https://www.youtube.com/watch?v=tfuZ7uZmVyg&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=7 npm install react-redux --save import {connect} from "react-redux"; import {Provider} from "react-redux"; <Provider store={store}> <App/> </Provider> const mapStateToProps = (state) => { return { user: state.userReducer, math: state.mathReducer } } const mapDispatchToProps = (dispatch) => { return { setName:(name)=>{ dispatch({ type:"SET_NAME", payload: name }); } } } export default connect(mapStateToProps,mapDispatchToProps)(app); <Main changeUsername={()=>this.props.setName("Anna")} /> <User username={this.props.user.name} /> ReactJS / Redux Tutorial - #8 Containers & Components (Smart & Dumb Components) https://www.youtube.com/watch?v=m2q3Dyr6To4&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=8 Dumb Components 只是方法不是類, 只須要return html不須要render. Smart Components放在containers文件夾下, Dumb Components放在components下. ReactJS / Redux Tutorial - #9 A better Project Structure https://www.youtube.com/watch?v=YmGm-qwbJdc&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=9 app actions, components, containers(app.js), reducers index.js store.js ReactJS / Redux Tutorial - #10 Async Actions https://www.youtube.com/watch?v=h892pHdLQtM&index=10&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ npm install redux-thunk --save import thunk from "redux-thunk"; applyMiddleware(logger(),thunk) npm install redux-promise-middleware --save import promise from "redux-promise-middleware"; applyMiddleware(logger(),thunk,promise()) return { type:"SET_NAME", payload:new Promise((resolve, reject) => { setTimeout(()=>{ resolve(name); },2000); }) } Reducer.js中 case "SET_NAME_FULFILLED" //由於這個promise中間件,須要加上_FULFILLED ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Learning React.js [1] - An Overview https://www.youtube.com/watch?v=vYldnghykaU&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO when a state is changed, the component is re-rendered and markup will be updated. This makes React very dynamic. Lifecycle Methods: render - Renders a component. The only one that is required. getInitialState - You can set default values for your states. getDefaultProps - Set defaults for properties. componentWillMount - Invoked once on client & server before render. componentDidMount - Invoked after the first render. React Addons: Collection of modules that aid in developing React.js applications Animation Addons 2 Way Data Binding Addons - React Link Testing Addons Learning React.js [2] - Your First Component https://www.youtube.com/watch?v=mDz4HXZHo9g&index=3&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO React網址: https://facebook.github.io/react/docs/getting-started.html <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> <script src="https://fb.me/react-0.14.7.js"></script> <script src="https://fb.me/react-dom-0.14.7.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.25/browser.min.js"></script> <script type="text/babel"> ... </script> Learning React.js [3] - Adding Properties https://www.youtube.com/watch?v=euSbXxCf88I&index=2&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO propTypes:{ title:React.PropTypes.string.isRequired }, getDefaultProps: function(){ return { title: "111", text: "222", link:"333" } } Learning React.js [4] - Events https://www.youtube.com/watch?v=CVigtRUxj2I&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO&index=4 <a onClick={this.OnClick.bind(this, 'Hello','Goodbye')}> //帶參數的function onClick: function(msg,msg2){ alert(msg2); //彈出Goodbye } Learning React.js [5] - State and Nesting Components https://www.youtube.com/watch?v=_o9NTYfbkR0&index=6&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO getInitialState: function(){ return { text: 'Hello World' } } <h1>{this.state.text}</h1> <input type="text" onChange={this.changeText} value={this.state.text} /> changeText: function(e){ this.setState({text: e.target.value}); //setState, e.target.value } Learning React.js [6] - Mapping Data https://www.youtube.com/watch?v=499IaPWLHKU&index=5&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO React中的循環: <ul className="list-group"> { this.props.todos.map(todo => { return <li className="list-group-item" todo={todo} key={todo.id}>{todo.name}</li> }) } <ul> Learning React.js [7] - Adding State Data Through a Form https://www.youtube.com/watch?v=yOu_PUAOtP0&index=7&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO App component: <TodoForm onTodoAdd={this.handleTodoAdd} /> handleTodoAdd: function(text){ var newTodo={ id: this.state.todos.length + 1, text: text } this.setState({todos: this.state.todos.concat(newTodo)}); //concat向數組裏面添加對象 } TodoForm component: <form onSubmit={this.onSubmit}> <input type="text" ref="text" onChange={this.onChange} className="form-control" /> //ref="text" </form> onSubmit:function(e){ //e參數, refs e.preventDefault(); var text = this.refs.text.value.trim(); if(!text){ alert('Please enter a todo'); return; } this.props.onTodoAdd(text); //調用傳過來的props方法onTodoAdd() this.refs.text.value=''; } Learning React.js [8] - Deleting State Data https://www.youtube.com/watch?v=AUso8hw2-JQ&index=8&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO <TodoList todos={this.state.todos} deleteTodo={this.handleTodoDelete} /> //這裏的handleTodoDelete不用指定參數 handleTodoDelete: function(todo){ var todos = this.state.todos; for(var i=0;i<todos.length;i++){ if(todos[i].id==todo.id){ todos.splice(i,1); } } this.setState({todos: todos}); } <a onClick={this.onDelete.bind(this,todo)} > onDelete(todo){ this.props.deleteTodo(todo); } Learning React.js [9] - Updating State Data https://www.youtube.com/watch?v=WI8Z1RKzhMM&index=9&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO <TodoForm {...this.state} onTodoAdd={this.handleTodoAdd} /> //{...this.state}會把整個state傳到控件TodoForm中,TodoForm控件中用{this.props.text}來得到state中的值. <TodoList //todos={this.state.todos} {...this.state} //{...this.state}會把整個state傳到該控件中 editTodo={this.handleTodoEdit} /> handleTodoEdit: function(todo){ this.setState({text:todo.text, isEdit: todo.id}); } <span onClick={this.editTodo.bind(this,todo)}> editTodo: function(todo){ this.props.editTodo(todo); } <TodoForm {...this.state} changeText={this.handleChangeText} onTodoUpdate={this.handleTodoUpdate} /> handleChangeText: function(text){ this.setState({text: text}); } handleTodoUpdate: function(todo){ var todos = this.state.todos; for(var i=0;i<todos.length;i++){ if(todos[i].id==todo.id){ todos.splice(i,1); } } todos.push(todo); this.setState({todos: todos}); } TodoForm 組件中: <input type="text" onChange={this.onChange}> onChange: function(e){ this.props.changeText(e.target.value); //input沒有onChange方法, 沒有this.props.changeText的話input中的值輸入會沒有變化 } onSubmit方法中: if(this.props.isEdit){ var updateTodo = { id: this.props.isEdit, text:text } this.props.onTodoUpdate(updatedTodo); }else{ this.props.onTodoAdd(text); } Learning React.js [10] Persisting Data To Firebase https://www.youtube.com/watch?v=QY7Ibl37_08&list=PLillGF-RfqbbKWfm3Y_RF57dNGsHnkYqO&index=10 頁面代碼中添加: <script src="https://cdn.firebase.com/js/client/1.0.17/firebase.js"></script> componentWillMount: function(){ this.firebaseRef = new Firebase('https://todolistdev1.firebaseio.com/todos'); var that = this; this.firebaseRef.once("value", function(snapshot){ //Get todo list from database var todos = []; snapshot.forEach(function(data){ var todo = { id: data.val().id, text: data.val().text } todos.push(todo); that.setState({todos: todos}); }); }); } Add: this.firebaseRef.push(newTodo); ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- React & Express Starter Pack For Full Stack Development https://www.youtube.com/watch?v=v0t42xBIYIs 項目模版的使用: git clone https://... npm install npm run client-install npm run dev //會同時啓動客戶端和服務端,由於使用了模塊concurrently. localhost:3000打開客戶端, localhost:5000/api/customers打開服務端. 建立項目: mkdir reactexpress cd reactexpress npm init npm i express concurrently npm i nodemon --save-dev package.json文件修改: "scripts":{ "start":"node server.js", "server":"nodemon server.js" } touch server.js //建立文件 code server.js //用vs code打開文件 npm run server //啓動服務端 打開另一個命令窗口: npm i -g create-react-app //安裝react的cli create-react-app client //建立react項目放在client下 打開client>package.json文件添加節點"proxy":"http://localhost:5000"指定服務端地址. npm start //啓動react客戶端 npm run dev同時啓動客戶端和服務端, 修改server端下面的package.json文件: "scripts":{ "client-install":"cd client && npm install", "start":"node server.js", "server":"nodemon server.js", "client":"npm start --prefix client", "dev":"concurrently \"npm run server\" \"npm run client\"" } -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- React JS Crash Course https://www.youtube.com/watch?v=A71aqufiNtQ 官網: https://facebook.github.io/rect npm install -g create-react-app create-react-app projectmanager //建立項目命令 npm start React使用的語法叫JSX. 生成GUID的插件: npm install --save uuid npm start import uuid from 'uuid'; uuid.v4(); //生成GUID 安裝jquery: npm install jquery --save npm start import $ from 'jquery'; react裏面不用name用ref? <input type="text" ref="title"> if(this.refs.title.value === '') child component: this.props.addProject(this.state.newProject); father component: <AddProject addProject={this.handleAddProject.bind(this)} /> handleAddProject(project){ console.log(project); } handleDeleteProject(id){ let projects=this.state.projects; let index=projects.findIndex(x=>x.id===id); //findIndex找到要刪除元素的序列號 projects.splice(index,1); this.setState({projects:projects}); } 類型驗證: Projects.propTypes={ projects:React.PropTypes.array, onDelete:React.PropTypes.func } setState有返回函數: this.setState({todos:data},function(){ console.log(this.state); }); state在構造函數中初始化, 在componentWillMount中賦值. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The 2017 React Development Starter Guide https://www.youtube.com/watch?v=7ojad6QYuqI Add Todo: this.state={ todoTitle:'' } this.handleInputChange=this.handleInputChange.bind(this); //放在構造函數裏面? handleInputChange(event){ const target = event.target; const target = event.target; const target = event.target; this.setState({ [name]:value }) } handleSubmit(event){ event.preventDefault(); this.props.onAddTodo(this.state); this.setState({ todoTitle:'' }); } <form onSubmit={this.handleSubmit.bind(this)}> <input type="text" id="inputTodoTitle" name="todoTitle" //能夠有name value={this.state.todoTitle} //綁定上面的todoTitle onChange={this.handleInputChange} //沒有這個方法輸入不了 /> 父Component中: handleAddTodo(todo){ this.setState({todos:[...this.state.todos, todo]}) } -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Learn Redux - Introduction To State Management With React https://www.youtube.com/watch?v=SGOFxK-28ns&index=1&list=PL2dKqfImstaSl8Hi6UrovwraEHvK2MNPt Component > Action > Store <> Reducer npm add redux //在react項目中添加redux package 建立src>actions>index.js One Action Example: export const voteReact = () =>{ return { type: 'VOTE_REACT' } } src>reducers>index.js reducer example: const initialState = { angular:0, react:0, vuejs:0 } export default (state = initialState, action) => { switch(action.type){ case 'VOTE_REACT': return Object.assign({},state,{ react:state.react + 1 }) default: return state } } 模版樣式:https://bootswatch.com 選擇Yeti, 加入public > Index.html 頁面樣式中. App.js: constructor(props){ super(props); this.store = this.props.store; //props是否是能夠理解爲parent?表示父控件中有屬性store } handleVoteReact = ()=>{ this.store.dispatch(voteReact()); //dispatch reducer } <div style={{'textAlign':'center'}}> //內聯樣式用雙引號 index.js: let store = createStore(myApp); function render(){ ReactDOM.render( <App store={store} />, document.getElementById('root') ); } store.subscribe(render); render(); {this.voteAngularInPercent().toFixed(2) + '%'} //這裏的this.voteAngularInPercent()是function -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Using Chart.js With React https://www.youtube.com/watch?v=Ly-9VTXJlnA 使用react-chartjs-2: https://github.com/gor181/react-chartjs-2 npm install -g create-react-app //安裝 create-react-app my-app //建立項目 cd my-app npm start npm install react-chartjs-2 chart.js --save 默認屬性: static defaultProps={ displayTitle:true, dsiplayLegend:true } 使用: this.props.displayTitle <Chart displayTitle=false /> //這裏的屬性值會覆蓋默認定義的屬性值 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Full Stack React & LoopBack [1] - Intro & LoopBack Server https://www.youtube.com/watch?v=Mx-cywTNy8s&list=PLillGF-RfqbZjJBAu0sx_0SCuFdzdx4iY&pbjreload=10 service mongod start //啓動mongodb服務 LoopBack - The Node.js API Framework: https://loopback.io/ npm install -g loopback-cli lb //建立項目 node . //啓動服務運行app npm install --save loopback-connector-mongodb lb datasource mongoDS --connector mongoDB //會自動建立文件生成代碼 lb model 按Enter鍵而後輸入model name Full Stack React & LoopBack [2] - React, Routing and UI https://www.youtube.com/watch?v=idvCKXXFGs4&index=2&list=PLillGF-RfqbZjJBAu0sx_0SCuFdzdx4iY 建立文件夾client_src用於存放React項目, 編譯後的文件存放於根目錄下的clinet文件夾. 用vs code打開client_src文件夾. create-react-app . //react項目建立於當前目錄下 使用指定端口, 修改package.json文件: "start":"set PORT=3001 && react-scripts start" //添加了set PORT=3001 && google搜索react router v4,打開https://reacttraining.com/react-router/, 要使用左側的<Switch>,<BrowserRouter> npm install --save react-router react-router-dom 建立router: src > components > Main.js, 把Main放在App component中:<Main /> 樣式: materializecss.com/ Full Stack React & LoopBack [3] - Fetching & Displaying Meetups https://www.youtube.com/watch?v=R3wiX05SJps&index=3&list=PLillGF-RfqbZjJBAu0sx_0SCuFdzdx4iY npm install axios --save //用於http通訊 this.setState({meetups: response.data}, ()=>{ //setState有回調函數 console.log(this.state); }); <Link to={`/meetups/${this.state.item.id}`}> Home </Link> //``符號內的變量${},EX6語法 獲取頁面地址欄傳過來的參數: let meetupId = this.props.match.params.id; Full Stack React & LoopBack [4] - Add, Edit & Delete Meetups https://www.youtube.com/watch?v=yN5qKqLDlpM&list=PLillGF-RfqbZjJBAu0sx_0SCuFdzdx4iY&index=4 <input type="text" name="name" ref="name" /> console.log(this.refs.name.value); this.handleInputChange = this.handleInputChange.bind(this); //放在構造函數裏面 handleInputChange(e){ const target = e.target; const value = e.target.value; const name = e.target.name; this.setState({ [name]:value }); } Edit頁面: <input type="text" name="name" ref="name" value={this.state.name} onChange={this.handleInputChange}/> //沒有onChange的方法就不能修改 Full Stack React & LoopBack [5] - Front & Back End Integration https://www.youtube.com/watch?v=M_PaFaIf6d8&index=5&list=PLillGF-RfqbZjJBAu0sx_0SCuFdzdx4iY 修改react的package.json文件: "build":"react-scripts build && cp -r build/* ../client/" //執行npm run build將編譯後的文件放到server端的client文件夾 vs code打開根項目文件夾,修改server > boot > root.js: router.get('/',server.loopback.status()); 改成router.get('/'); middleware.json: "files":{ "loopback#static":{ "params":"$!../client" } } node . //啓動項目 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Build & Deploy A React JS Text Generator App https://www.youtube.com/watch?v=yU5DYccb77A 返回text的API: hipsterjesus.com npm install axios --save //axios網址 https://github.com/mzabriskie/axios import axios from 'axios' onChange(e){ this.setState({value: e.target.value}, function(){ //e.target.value this.props.onChange(this.state.value); }) } <br /> //jsx語法中必需要有/,不能是<br> npm run build //編譯項目到build文件夾, 裏面有個static文件夾 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ReactJS Basics - #2 Setup Workspace with Webpack https://www.youtube.com/watch?v=uextYhQGP6k&list=PL55RiY5tL51oyA8euSROLjMFZbXaV7skS&index=2 npm init npm install react react-dom --save npm install webpack webpack-dev-server babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-2 --save-dev //webpack-dev-server會自動刷新頁面 根目錄下建立webpack.config.js git init .gitignore: /node_modules /dist /npm-debug.log git add . git commit -m "initial commit, setup finished" git checkout -b 01-setup //建立分支? react propTypes 說明文檔: https://facebook.github.io/react/docs/reusable-components.html Component內部屬性: <Home> <p>This is a paragraph!</p> </Home> {this.props.children} Home.propTypes = { children: React.PropTypes.element.isRequired } <button onClick={() => this.onMakeOlder()} > //事件的這種寫法不須要綁定this ReactJS Basics - #10 Stateless Components https://www.youtube.com/watch?v=SEkfzqIgvTo&index=11&list=PL55RiY5tL51oyA8euSROLjMFZbXaV7skS export const Header = (props) => { return ( <p>{props.homeLink}</p> ) } console.log("123",nextProps,nextState) //console.log跟Python裏面的Print方法相似 ReactJS Basics - #15 React Router - Route Setup https://www.youtube.com/watch?v=eofpZPRUnP8&list=PL55RiY5tL51oyA8euSROLjMFZbXaV7skS&index=16 npm install --save react-router import {Router,Route,browserHistory,IndexRoute} from "react-router"; render(){ return ( <Router history={browserHistory}> <Route path={"/"} component={Root}> <IndexRoute component={Home} /> <Route path={"user/:id"} component={User} /> <Route path={"home"} component={Home} /> </Route> <Route path={"home-single"} component={Home} /> </Router> ); } package.json: "build"最後追加 --history-api-fallback ReactJS Basics - #16 React Router - Navigation & Parameters https://www.youtube.com/watch?v=5pt_igBTCsI&list=PL55RiY5tL51oyA8euSROLjMFZbXaV7skS&index=17 方法一: import {Link} from "react-router"; <Link to={"/home"} activeStyle={{color:"red"}}>Home</Link> <Link to={"/user/10"} activeClassName={"active"}>User</Link> 方法二: import {browserHistory} from "react-router"; onNavigateHome(){ browserHistory.push("/home"); } <button onClick={this.onNavigateHome}>Go Home</button> 帶參數: {this.props.params.id} React Router文檔: https://github.com/reactjs/react-router-tutorial/tree/master/lessons -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ReactJS / Redux Tutorial - #3 Using Redux https://www.youtube.com/watch?v=ZKCYqJu4n3s&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=3 Start the Webpack Dev Server with npm run build and then visit http://localhost:8080 npm install redux --save import {createStore} from "redux"; const reducer = (state,action) => { switch(action.type){ case "ADD": state = state + action.payload; break; case "SUBTRACT": break; } return state; }; const store = createStore(reducer,1); //第二個參數1是初始的state store.subscribe(()=>{ console.log("Store updated!", store.getState()); }); store.dispatch({ type: "ADD", payload: 10 }); ReactJS / Redux Tutorial - #4 Working with State and Immutability https://www.youtube.com/watch?v=7bMTJxvEJiE&index=4&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ const initialState = { result:1, lastValues:[] } const reducer = (state = initialState,action) => { switch(action.type){ case "ADD": //state.result += action.payload; state={ ...state, //得到old state result: state.result + action.payload, //覆蓋原result lastValues: [...state.lastValues, action.payload] //數組裏面用... } break; case "SUBTRACT": break; } return state; }; ReactJS / Redux Tutorial - #5 Multiple Reducers https://www.youtube.com/watch?v=BVvBa18o8Es&index=5&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ import {createStore, combineReducers} from "redux"; const store = createStore(combineReducers({mathReducer, userReducer})); //createStore不能直接傳遞多個reducer參數,因此使用combineReducers ReactJS / Redux Tutorial - #6 Redux Middleware https://www.youtube.com/watch?v=AgO7YcJeBh4&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_&index=6 import {createStore, combineReducers, applyMiddleware} from "redux"; //applyMiddleware const myLogger = (store) => (next) => (action) => { console.log("Logged Action: ", action); next(action); } const store = createStore(combineReducers({mathReducer, userReducer}),{}, applyMiddleware(myLogger)); 實用的Middleware: npm install redux-logger --save import logger from "redux-logger"; const store = createStore(combineReducers({mathReducer, userReducer}),{}, applyMiddleware(logger())); ReactJS / Redux Tutorial - #7 Connect ReactJS and Redux https://www.youtube.com/watch?v=tfuZ7uZmVyg&index=7&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ npm install react-redux --save import {Provider} from "react-redux"; index.js: import App from "./components/App"; //若是是default component這不須要{}, 例如這裏是App而不是{App} render( <Provider store={store} <App/> </Provider>, window.document.getElementById('app'); ); App.js: import {connect} from "react-redux"; <Main changeUsername={()=>this.props.setName("Anna")}/> <User username={this.props.user.name} /> const mapStateToProps = (state) => { return { user: state.user, //key是屬性, 這裏的user是屬性 math: state.math } } const mapDispatchToProps = (dispatch) => { return { setName:(name)=>{ dispatch({ type:"SET_NAME", payload:name }); } } } export default connect(mapStateToProps, mapDispatchToProps)(App); //connect this component to store ReactJS / Redux Tutorial - #8 Containers & Components (Smart & Dumb Components) https://www.youtube.com/watch?v=m2q3Dyr6To4&index=8&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ Smart Component: know state. 放在Containers文件夾下 Dumb Component: unknow state. 放在Components文件夾下. 使用export const Main = (props) =>{} ReactJS / Redux Tutorial - #9 A better Project Structure https://www.youtube.com/watch?v=YmGm-qwbJdc&index=9&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ app文件夾下建立reducers,actions文件夾,建立store.js文件. ReactJS / Redux Tutorial - #10 Async Actions https://www.youtube.com/watch?v=h892pHdLQtM&index=10&list=PL55RiY5tL51rrC3sh8qLiYHqUV3twEYU_ npm install redux-thunk --save //解決錯誤Actions must be plain objects. Use custom middleware for async actions. store.js: import thunk from "redux-thunk"; applyMiddleware(thunk) userActions.js: return { type:"SET_NAME", payload: new Promise((resolve, reject) => { setTimeout(()=>{ resolve(name); },2000); }); } npm install redux-promise-middleware --save store.js: import promise from "redux-promise-middleware"; applyMiddleware(promise()) userReducer修改action name to SET_NAME_FULFILLED //添加後綴_FULFILLED, 使用promise()的時候須要添加. React | Redux 使用文檔: redux.js.org/docs/basics/UsageWithReact.html -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ReactJS從入門到實戰 11 11 表單元素 https://www.youtube.com/watch?v=hJxRcG1APbQ&t=653s&index=5&list=WL var styles={ //styles是對象,定義在組件外面 inputText:{ width:100, fontSize:24 //這裏是fontSize而不是font-size } } getInitialState:function(){ return{ input:'default' } }, handleTextChange: function(evt){ this.setState({'input': evt.target.value}); } <input type='text' style={styles.inputText} value={this.state.input} onChange={this.handleTextChange} defaultValue={this.state.input}/> <textarea style={styles.inputText} onChange={this.handleTextChange} defaultValue={this.state.input} /> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Redux Crash Course With React https://www.youtube.com/watch?v=93p3LxR9xfM VS Code插件: ES7 React/Redux/GraphQL/React-Native snippets npm start //啓動react dev server,打開localhost:3000 react component code snippet: 'rcc'. 'rfc' code snippet for function. 頁面上有多個輸入框: <input type="text" name="title" onChange={this.onChange} value={this.state.title}/> constructor中: this.onChange = this.onChange.bind(this); constructor外render外: onChange(e){ this.setState({[e.target.name]: e.target.value}); } Add Post: //新增 <form onSubmit={this.OnSubmit.bind(this)}> OnSubmit(e){ e.preventDefault(); const post={ title:this.state.title, body:this.state.body } fetch('https://jsonplaceholder.typicode.com/posts',{ method:'POST', headers:{ 'content-type':'application/json' }, body:JSON.stringify(post) }) .then(res=>res.json()) .then(data=>console.log(data)); } 安裝Redux相關插件: npm i redux react-redux redux-thunk App.js導入Provider 和 store: import {Provider} from 'react-redux'; import store from './store'; //建立單獨的store.js文件 內容包裹在<Provider>裏面: render(){ return( <Provider store={store}> ... </Provider> ); } 錯誤'react-scripts' is not recognized as an internal or external command. 解決方案:npm install redux官方文檔地址: https://github.com/reactjs/redux/tree/master/docs/api store.js: import {createStore,applyMiddleware} from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; ... 建立rootReducer, reducers/index.js: import {combineReducers} from 'redux'; import postReducer from './postReducer'; export default combineReducers({ posts: postReducer }); export function fetchPosts(){ return function(dispatch){ ... } } 簡化後的寫法是: export const fetchPosts=()=>dispatch=>{...} 組件Posts.js中: import {connect} from 'react-redux'; //connect the store to the component componentWillMount(){ this.props.fetchPosts(); //props下的action } const mapStateToProps = state => ({ posts: state.posts.items //使用的時候用this.props.posts }); export default connect(mapStateToProps,{fetchPosts})(Posts); //若是沒有mapStateToProps,則爲null import PropTypes from 'prop-types'; Posts.propTypes={ fetchPosts:PropTypes.func.isRequired, posts:PropTypes.array.isRequired } 谷歌Redux插件: Google搜索chrome extension redux 點擊 Redux DevTools - Chrome Web Store 要使用以上插件,修改store.js: import {createStore, applyMiddleware, compose} from 'redux'; const store = createStore( rootReducer, initialState, compose( applyMiddleware(...middleware), window.__REDUX_DEVTOOLS_EXTENSION__&& window.__REDUX_DEVTOOLS_EXTENSION__() ) ); Redux裏面的state是application級別的,不是某個Component的state. dispatch裏面包括type和payload(要傳遞的值). componentWillReceiveProps(nextProps){ //when it receives property from state if(nextProps.newPost){ this.props.posts.unshift(nextProps.newPost); //push會添加到數組的最後一位,unshift添加到數組的最前面 } } ----------------------------------------------------------------------------------------------------------------------------------------------------------------------