那個時候剛學react,不知道面試官說的元素是什麼,如今知道了,就是虛擬dom嘛。。。html
React 元素(React element)react
它是 React 中最小基本單位,咱們可使用 JSX 語法輕鬆地建立一個 React 元素:面試
const element = <div className="element">I'm element</div> 複製代碼
React 元素不是真實的 DOM 元素,它僅僅是 js 的普通對象(plain objects),因此也沒辦法直接調用 DOM 原生的 API。上面的 JSX 轉譯後的對象大概是這樣的:算法
{ _context: Object, _owner: null, key: null, props: { className: 'element', children: 'I'm element' }, ref: null, type: "div" } 複製代碼
除了使用 JSX 語法,咱們還可使用 React.createElement() 和 React.cloneElement() 來構建 React 元素。設計模式
React 組件api
React 中有三種構建組件的方式。React.createClass()、ES6 class和無狀態函數。數組
一、React.createClass()瀏覽器
var Greeting = React.createClass({ render: function() { return <h1>Hello, {this.props.name}</h1>; } }); 複製代碼
二、ES6 classbash
class Greeting extends React.Component{ render: function() { return <h1>Hello, {this.props.name}</h1>; } }; 複製代碼
三、無狀態函數markdown
無狀態函數是使用函數構建的無狀態組件,無狀態組件傳入props和context兩個參數,它沒有state,除了render(),沒有其它生命週期方法。
function Greeting (props) { return <h1>Hello, {props.name}</h1>; } 複製代碼
四、PureComponent
除了爲你提供了一個具備淺比較的shouldComponentUpdate方法,PureComponent和Component基本上徹底相同。
元素與組件的區別
組件是由元素構成的。元素數據結構是普通對象,而組件數據結構是類或純函數。
是父組件用來獲取子組件的dom元素的,爲何有這個API,緣由以下
// 例若有一個子組件和父組件,代碼以下 子組件爲: class Child extends React.Component{ constructor(props){ super(props); } render(){ return <input /> } } // 父組件中,ref: class Father extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <Child ref={this.myRef}/> } } 複製代碼
此時父組件的this.myRef.current的值是Child組件,也就是一個對象,若是用了React.forwardRef,也就是以下
// 子組件 const Child = React.forwardRef((props, ref) => ( <input ref={ref} /> )); // 父組件 class Father extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } componentDidMount() { console.log(this.myRef.current); } render() { return <Child ref={this.myRef} /> } } 複製代碼
此時父組件的this.myRef.current的值是input這個DOM元素
注:答案參考司徒正美大神的文章
class Input extends Component{ constructor(){ super(); this.state = {val:'100'} } handleChange = (e) =>{ //e是事件源 let val = e.target.value; this.setState({val}); }; render(){ return (<div> <input type="text" value={this.state.val} onChange={this.handleChange}/> {this.state.val} </div>) } } 複製代碼
class Sum extends Component{ constructor(){ super(); this.state = {result:''} } //經過ref設置的屬性 能夠經過this.refs獲取到對應的dom元素 handleChange = () =>{ let result = this.refs.a.value + this.b.value; this.setState({result}); }; render(){ return ( <div onChange={this.handleChange}> <input type="number" ref="a"/> {/*x表明的真實的dom,把元素掛載在了當前實例上*/} <input type="number" ref={(x)=>{ this.b = x; }}/> {this.state.result} </div> ) } } 複製代碼
使用 react 常常會遇到幾個組件須要共用狀態數據的狀況。這種狀況下,咱們最好將這部分共享的狀態提高至他們最近的父組件當中進行管理。咱們來看一下具體如何操做吧。
import React from 'react' class Child_1 extends React.Component{ constructor(props){ super(props) } render(){ return ( <div> <h1>{this.props.value+2}</h1> </div> ) } } class Child_2 extends React.Component{ constructor(props){ super(props) } render(){ return ( <div> <h1>{this.props.value+1}</h1> </div> ) } } class Three extends React.Component { constructor(props){ super(props) this.state = { txt:"牛逼" } this.handleChange = this.handleChange.bind(this) } handleChange(e){ this.setState({ txt:e.target.value }) } render(){ return ( <div> <input type="text" value={this.state.txt} onChange={this.handleChange}/> <p>{this.state.txt}</p> <Child_1 value={this.state.txt}/> <Child_2 value={this.state.txt}/> </div> ) } } export default Three 複製代碼
高階組件不是組件,是 加強函數,能夠輸入一個元組件,返回出一個新的加強組件
function proxyHoc(WrappedComponent) { return class extends React.Component { render() { const newProps = { count: 1 } return <WrappedComponent {...this.props} {...newProps} /> } } } 複製代碼
const MyContainer = (WrappedComponent)=>{ return class extends WrappedComponent { render(){ return super.render(); } } } 複製代碼
Context 經過組件樹提供了一個傳遞數據的方法,從而避免了在每個層級手動的傳遞 props 屬性。
import React,{Component} from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; class Header extends Component{ render() { return ( <div> <Title/> </div> ) } } class Title extends Component{ static contextTypes={ color:PropTypes.string } render() { return ( <div style={{color:this.context.color}}> Title </div> ) } } class Main extends Component{ render() { return ( <div> <Content> </Content> </div> ) } } class Content extends Component{ static contextTypes={ color: PropTypes.string, changeColor:PropTypes.func } render() { return ( <div style={{color:this.context.color}}> Content <button onClick={()=>this.context.changeColor('green')}>綠色</button> <button onClick={()=>this.context.changeColor('orange')}>橙色</button> </div> ) } } class Page extends Component{ constructor() { super(); this.state={color:'red'}; } static childContextTypes={ color: PropTypes.string, changeColor:PropTypes.func } getChildContext() { return { color: this.state.color, changeColor:(color)=>{ this.setState({color}) } } } render() { return ( <div> <Header/> <Main/> </div> ) } } ReactDOM.render(<Page/>,document.querySelector('#root')); 複製代碼
Portals 提供了一種很好的將子節點渲染到父組件之外的 DOM 節點的方式。
ReactDOM.createPortal(child, container)
複製代碼
第一個參數(child)是任何可渲染的 React 子元素,例如一個元素,字符串或碎片。第二個參數(container)則是一個 DOM 元素。
部分 UI 中的 JavaScript 錯誤不該該破壞整個應用程序。 爲了解決 React 用戶的這個問題,React 16引入了一個 「錯誤邊界(Error Boundaries)」 的新概念。
import React from 'react'; import ReactDOM from 'react-dom'; class ErrorBoundary extends React.Component{ constructor(props) { super(props); this.state={hasError:false}; } componentDidCatch(err,info) { this.setState({hasError: true}); } render() { if (this.state.hasError) { return <h1>Something Went Wrong</h1> } return this.props.children; } } class Page extends React.Component{ render() { return ( <ErrorBoundary> <Clock/> </ErrorBoundary> ) } } class Clock extends React.Component{ render() { return ( <div>hello{null.toString()}</div> ) } } ReactDOM.render(<Page/>,document.querySelector('#root')); 複製代碼
增長dangerouslySetInnerHTML屬性,而且傳入對象的屬性名叫_html
function Component(props){ return <div dangerouslySetInnerHTML={{_html:'<span>你好</span>'}}> </div> } 複製代碼
舉例說明
變化前數組的值是[1,2,3,4],key就是對應的下標:0,1,2,3
變化後數組的值是[4,3,2,1],key對應的下標也是:0,1,2,3
複製代碼
變化前數組的值是[1,2,3,4],key就是對應的下標:id0,id1,id2,id3
變化後數組的值是[4,3,2,1],key對應的下標也是:id3,id2,id1,id0
複製代碼