菜鳥官方解釋:css
React 是一個用於構建用戶界面的 JAVASCRIPT 庫。html
React主要用於構建UI,不少人認爲 React 是 MVC 中的 V(視圖)。vue
React 起源於 Facebook 的內部項目,用來架設 Instagram 的網站,並於 2013 年 5 月開源。react
React 擁有較高的性能,代碼邏輯很是簡單,愈來愈多的人已開始關注和使用它android
React特色:ios
1.聲明式設計 −React採用聲明範式,能夠輕鬆描述應用。json
2.高效 −React經過對DOM的模擬,最大限度地減小與DOM的交互。小程序
3.靈活 −React能夠與已知的庫或框架很好地配合。瀏覽器
4.JSX − JSX 是 JavaScript 語法的擴展。React 開發不必定使用 JSX ,但咱們建議使用它。緩存
5.組件 − 經過 React 構建組件,使得代碼更加容易獲得複用,可以很好的應用在大項目的開發中。
6.單向響應的數據流 − React 實現了單向響應的數據流,從而減小了重複代碼,這也是它爲何比傳統數據綁定更簡單。
state建立數據
jsx 模板
數據 + 模板 生成Virtual DOM(虛擬節點就是js建立的一個對象,該對象是對節點的一個描述,包含了該節點的全部信息,attrs,content等)
用虛擬DOM生成真實的DOM,顯示
state改變
數據 + 模板生成新的 Virtual DOM
對比新舊Virtual DOM的區別,找到區別。
直接操做DOM改變有區別的地方。
注:由於瀏覽器在解析網頁時,js和html是分開的。就至關於兩個模塊,js要跨越界限操道別人的東西,因此說代價是比較大的。虛擬dom的建立使得性能很大程度提高,且他的應用 使得跨端應用得意實現 React Native.在android和ios端是不存在dom一說的,因此在建立虛擬dom後,會將虛擬dom生成對應的原生的東西。
字義即:漸進式Web應用
PWA有能夠實現什麼呢?
能夠將app的快捷方式放置到桌面上,全屏運行,與原生app無異
可以在各類網絡環境下使用,包括網絡差和斷網條件下,不會顯示undefind
推送消息的能力
其本質是一個網頁,沒有原生app的各類啓動條件,快速響應用戶指令
在React.js中。public文件夾下有一個mainfest.json的文件夾,該文件就是用來實現桌面快捷方式的配置,而無網絡狀況,或網絡狀況較差時,則使用service worker來實現離線緩存。
Web離線引用解決方案。指在在進過網頁後,當網絡斷開鏈接後,依然能夠再次訪問頁面。
ServiceWorker的主要能力集中在網絡代理和離線緩存上。具體的實現上,能夠理解爲ServiceWorker是一個能在網頁關閉時仍然運行的WebWorker
在經過react腳手架建立項目後,src根目錄下是有一個serviceWorker.js文件的,該文件就是用來寫app時,提供離線緩存技術。供線下仍可正常訪問。
保證state中的數據不被修改。修改數據時,不能經過this.state.xx來就該數據須要用特定的方法this.setState({});能夠發現和小程序也是同樣的了
百度解釋:
JSX是一種JavaScript的語法擴展,運用於React架構中,其格式比較像是模版語言,但事實上徹底是在JavaScript內部實現的。元素是構成React應用的最小單位,JSX就是用來聲明React當中的元素,React使用JSX來描述用戶界面。
詳細使用:JSX
render() { return ( <div> <ul> <li></li> </ul> </div> ) }
上面代碼等同於下面
render() { return React.createElement('div',{},React.createElement('ul',{},React.craeteElement('li',{}))); }
他的順序:jsx => createElement => Virtual Dom => 真實Dom
vue和react的虛擬節點的渲染實際上是一致的
在設置樣式時,咱們原來都是經過添加class或者id來設置對應的類名,在react中由於建立模板時使用的就是class類,因此在渲染模板時,樣式的設置能夠經過className=""來設置
每一個組件都要求有大的標籤包裹,可是會產生沒必要要的DOM,所以react提供了Fragment來坐佔位符。這樣就不會產生新的節點,且組件不會抱任何錯誤。
import React, { Component,Fragment } form 'react'; class Demo extends Component { render() { return ( <Fragment> Html content </Fragment> ) } }
在render中若是要使某些內容不被轉義。
則咱們就須要使用dangerouslySetInnerHTML來保持元素不被轉義
<div dangerouslySetInnerHTML={{ __html: '<div>123</div>' }} />
dangerouslySetInnerHTMl 是React標籤的一個屬性,相似於angular的ng-bind;
有2個{{}},第一{}表明jsx語法開始,第二個是表明dangerouslySetInnerHTML接收的是一個對象鍵值對;
既能夠插入DOM,又能夠插入字符串;
可是存在一個問題,由於使用標籤內容後會將其轉換,因此頗有可能遭到XSS攻擊。
import React,{ Component,Fragment } from 'react'; import './style/todoList.css' class TodoList extends Component { constructor(props) { super(props); this.state = { inputValue: '', list: [] } this.handleInputChange = this.handleInputChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } render() { return ( <Fragment> {/**這裏是註釋 */} <input className="input" onChange={this.handleInputChange.bind(this)} value={this.state.inputValue} /> <button className="btn" onClick={this.handleSubmit}>提交</button> <ul> { this.state.list.map((item,index) => { return ( <li key={index} onClick={this.handleDeleteItem.bind(this,index)} dangerouslySetInnerHTML={{__html:item}} > </li> ) }) } </ul> </Fragment> ) }; handleInputChange(e) { this.setState({ inputValue: e.target.value }) }; handleSubmit() { this.setState({ list: [...this.state.list,this.state.inputValue], inputValue: '' }) }; handleDeleteItem(index) { let list = [...this.state.list]; list.splice(index,1); this.setState({ list: list }) } } export default TodoList;
當咱們在input中輸入<h1>Hello World</h1>時,若是使用了dangerouslySetInnerHTML的話,h1標籤就會生效。
在使用label時,通常咱們會經過for與input上的id進行綁定。在react中,咱們則須要經過htmlFor=""來綁定input
父傳子經過屬性傳遞,將須要傳遞的數據放在子組件上,經過屬性的方式傳遞,子組件經過this.props.attr則就能夠獲取到父組件傳遞過來的數據
父組件:
import TodoItem from './TodoItem' render() { return ( <ul> { this.state.list.map((item,index) => { return ( <div> <TodoItem content={item} index={index} /> {/*<li key={index} onClick={this.handleItemDelete.bind(this,index)} dangerouslySetInnerHTML={{__html:item}} > </li>*/} </div> ) }) } </ul> ) }
給子組件將數據掛在到content和index上,
import React, { Component } from "react"; class TodoItem extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } render() { return ( <div>{this.props.content}</div> ) } } export default TodoItem;
經過this.props就能夠獲取到父組件傳遞過來的數據。
子傳父的話,沒有vue那麼多的方法,這裏須要在父組件先將方法傳遞給子組件。
將方法經過屬性的方式掛在到子組件上,不過須要注意的是,這裏須要綁定指向爲父組件
仍是剛纔的內容
import React,{ Component,Fragment } from 'react'; import TodoItem from './TodoItem'; import './style/todoList.css'; class TodoList extends Component { constructor(props) { super(props); this.state = { inputValue: '', list: [] } this.handleInputChange = this.handleInputChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.handleItemDelete = this.handleItemDelete.bind(this); } render() { return ( <Fragment> <div> <label htmlFor="inputArea">輸入內容</label> <input id="inputArea" className="input" onChange={this.handleInputChange} value={this.state.inputValue} /> <button className="btn" onClick={this.handleSubmit} >提交</button> </div> <ul> {this.getTodoItem()} </ul> </Fragment> ) }; getTodoItem() { return this.state.list.map((item,index) => { return ( <TodoItem key={index} content={item} index={index} deleteItem={this.handleItemDelete} /> ) }) }; handleInputChange(e) { const value = e.target.value; this.setState(() => ({ inputValue: value })) }; handleSubmit() { this.setState((prevState) => ({ list: [...prevState.list,prevState.inputValue], inputValue: '' })) }; handleItemDelete(index) { this.setState((prevState) => { const list = [...prevState.list]; list.splice(index,1); return {list} }) } } export default TodoList;
deleteItem就是掛在的方法,供子組件調用
子組件
import React, { Component } from "react"; class TodoItem extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } render() { const { content }= this.props; return ( <div onClick={this.handleClick}> {content} </div> ) } handleClick() { const { deleteItem,index } = this.props; deleteItem(index); } } export default TodoItem;
注:react是單向數據流,舉這樣一個例子:父組件引用了5個子組件,每一個子組件都引用了父組件傳遞的list.若是不是單向數據流,子組件在對this.props.list= [];作出修改後,其餘4個子組件會怎樣?
顯示這就是一個bug了,修改一個其餘的都修改了。顯然是一個比較嚴重的問題。因此react單向數據裏就是解決這樣一個問題。
父組件傳遞給子組件的數據,是沒法作出修改的。state中的數據有一個只讀屬性,是沒法作出修改的。若是非要修改,須要父組件傳遞給子組件一個方法,子組件經過調用該方法來實現數據的更改。
該方法用來更新state數據,調用該方法時,就算state中的數據沒有作修改,也會從新執行render方法。
setState({ isActive: true, }) console.log(this.state.isActive)//false
async handleClick() { await this.setState({ isActive: true }) console.log(this.state.isActive);//true }
該方法有兩個參數
setState((prevState) => { //prevState是舊的數據 },()=> { //這裏能夠獲得更新之後的數據 })
組件間傳值時,對接受數據的一個限制
詳細doc可查看官網https://reactjs.org/docs/typechecking-with-proptypes.html
import { PropTypes } from 'prop-types' class 組件 extends Component {} 組件.propTypes = { optionalArray: PropTypes.array, optionalBool: PropTypes.bool, optionalFunc: PropTypes.func, optionalNumber: PropTypes.number, optionalObject: PropTypes.object, optionalString: PropTypes.string, optionalSymbol: PropTypes.symbol, }
組件.propTypes = {
obj: PropTypes.string.isRequired
}
要求類型能夠爲多項
組件.propTypes = {
obj: PropTypes.arrayOf(PropTypes.number,PropTypes.string)
}
爲組件間傳值的對象設置默認值
class 組件 extends Component {} 組件.defaultProps = { obj1: 'hello world' }
設置默認值後,父組件在未傳遞數據時,會默認使用該默認值
後續繼續學習更新