React知识点

一、react 基本知识

  • JSX基本使用
  • setState ***
  • 生命周期
  • 条件
  • 列表
  • 事件
  • 表单
  • 组件 跟 props

1. jsx语法

  • 语法:html 属性名请使用小驼峰(camelCase)写法

    const element = <h1>Hello, world!</h1>;
    
    // 函数形式,return为最终拿到的html结构
    function Element(props) {
       return (
         <h1>Hello, world!</h1>
       )
    }
    
  • 小括号括:可以将 HTML 语句写为多行以增加可读性,用小括号括起来可以防止自动插入分号导致的错误

    const element = (
      <h1>
        Hello, {formatName(user)}!
      </h1>
    );
    
  • 可用表达式,如 for 和 if 中:

      function getGreeting(user){
        if (user){
          return <h1>Hello, {formatName(user)}!</h1>;
        }
        return <h1>Hello, Stranger.</h1>;
      }
    
  • babel 会编译 JSX 成 React.createElement() 的参数调用

    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    // 编译为以下形式
    const element = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    // React.createElement() 会生成这样一个对象(React 元素):
    const element = {
      type: 'h1',
      props: {
        className: 'greeting',
        children: 'Hello, world'
      }
    };
    

2. 元素渲染: 通过 ReactDOM.render() 方法很轻松的把内容渲染到了目标容器上。

  • ReactDOM.render(“要渲染的jsx内容”, “渲染到哪个节点上做绑定”);
  1. 定时更新时钟的例子

    function Tick(){
      const element = (
        <div>
          <h1>Hello, world!</h1>
          <h2>It is {new Date().toLocaleTimeString()}.</h2>
        </div>
      );
    
      ReactDOM.render(
        element,
        document.getElementById('root')
      );
    }
    
    setInterval(Tick, 1000);
    
    // 组件方式(jsx语法):重写上面时钟,时间作为变量动态传入jsx结构中
    function Clock(props){
      return (
        <div>
          <h1>Hello, world!</h1>
          <h2>It is {props.date.toLocaleTimeString()}.</h2>
        </div>
      );
    }
    
    function Tick(){
      ReactDOM.render(
        <Clock date={new Date()} />,
        document.getElementById('root')
      );
    }
    
    setInterval(Tick, 1000);
    

3.setState*

  • 不可变值

    • 不可变值(纯函数)— 数组,不能直接对 this.state.list 进行 push 、pop、splice等,这样违反不可变值

      count list5Copy = this.state.list5.slice();
      list5Copy.splice(2, 0, "a");
      
      this.setState({
        list1: this.state.list1.concat(100), //追加
        list2: [...this.state.list2, 100], //追加
        list3: this.state.list3.slice(0, 3), //截取
        list4: this.state.list4.filter(item => {item => item > 100}), //筛选
        list5: list5Copy //其他操作
      })
      
    • 不可变值— 对象,不能直接对 this.state.obj 进行属性设置,这样违反不可变值

      this.setState({
        obj1: Object.assign({}, this.state.obj1, {a: 100}),
        obj2: {...this.state.obj2, a: 100}
      })
      
  • 可能是异步

    • 异步更新回调

      this.setState({
        count: this.state.count + 1
      }, () => {
         //跟 Vue $nextTick 类似
      })
      
    • 直接使用setState是异步更新状态值。(主线程执行完才执行异步线程)

      this.setState({
        count: this.count + 1
      })
      console.log("count的值:" + count);
      
      //注:界面看到count已经加1了,但是控制台打印出来的确是原始的值。
      
    • 在setTimeout中使用是同步的

    • 在自定义的Dom事件中,setStateshi 同步的

      clickHandle = () => {
        this.setState({
          count: this.count + 1
        })
      }
      componentDidMount() {
         // 自定义的Dom事件,setState 是同步的
        document.body.addEventListener("click", this.clickHandle)
      }
      
  • 可能会被合并

    • setState传入对象,会被合并

      constructor(props) {
        this.state = {
          count:0
        }
      }
      
      this.setState({
        count: this.state.count + 1
      })
      this.setState({
        count: this.state.count + 1
      })
      this.setState({
        count: this.state.count + 1
      })
      
      // 执行结果:1,因为setState异步更新,当要异步更新的时候取到count都是为加1的值。
      
    • 传入函数,不会被合并,执行结果 是 + 3

      constructor(props) {
        this.state = {
          count:0
        }
      }
      this.setState((prevState, props) => {
        return {
          count: prevState.count + 1
        }
      })
      this.setState((prevState, props) => {
        return {
          count: prevState.count + 1
        }
      })
      this.setState((prevState, props) => {
        return {
          count: prevState.count + 1
        }
      })
      

4.组件的生命周期

  1. 单组件生命周期(对比vue)
    • react挂载时:constructor —> render, 渲染jsx —> React 更新 DOM 跟refs —> component-DidMount,一般用来访问ajax
    • react更新时:setState( ) —> shouldComponent-Update,决定是否继续渲染 —> render,渲染jsx —> React 更新 DOM 跟refs —> componentDidUpdate
    • react卸载时:componentWill-Unmount, 一般用来卸载定时器,清除挂载的Dom事件
    • vue挂载时:beforeCreate —> created —> beforeMount —> mounted,一般用来访问ajax
  2. 父子组件生命周期,和Vue的一样

5. 组件:state、lifecycle、事件、条件判断、列表循环、表单绑定变量

  • React 要求所有组件函数都必须是纯函数
  • 如果一个函数执行过程中不改变其参数,也不改变其外部作用于参数,当相同的输入总能得到相同的值时,我们称之这样的函数为纯函数。
  • 组件名的首字母大写。
  • render 方法的返回值描述了你希望在屏幕上看到的内容
  1. 时间功能用react组件方式实现:

    • 新建一个类,类名同组件函数名Clock,并继承自 React.Component
    • 给该类添加一个方法 render(/无参数/), 放置原来clock的jsx代码
    • 将 render 方法中的 props 换为 this.props,父组件给子组件值也是通过属性传递。
    class Clock extends React.Component {
      render(){
        return (
          <div>
            <h1>Hello, world!</h1>
            <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
          </div>
        );
      }
    }
    
  2. 利用state,lifecycle(生命周期函数):实现时钟组件自动更新时间功能

    class Clock extends React.Componet {
      constructor(props) {
        super(props);  //必须写, 固定格式
        this.state = {
          date: new Date()
        }
      }
      
      tick(){
        this.setState({
          date: new Date()
        });
      }
      // 渲染(render方法)完成时立即执行
      componentDidMount(){
        this.timerID = setInterval(
          () => this.tick(),
          1000
        );
      }
      // render 的内容即将被移除前执行
      componentWillUnmount(){
        clearInterval(this.timerID);
      }
      
      render() {
        return(
          <div>
              <div>
            <h1>Hello, world!</h1>
            <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
          </div>
        )
      }
    }
    
  3. 组件中的事件:

    • 事件名使用小驼峰写法,而不是全小写,例如:onclick 写作 onClick
    • 注册事件使用花括号表达式替代原有函数写法
    • 无法通过事件函数 return false 的方式阻止默认事件,必须显式的调用 preventDefault()
    • *****注:this指向要注意,不是箭头函数都容易出错
    class Button extends React.Component {
      constructor(){
        super();
        this.name = "Bob";
        // 一般用这种方式修正事件函数 this 绑定:写个跟事件函数同名的属性click,赋值为事件函数并修改其this指向
        this.click = this.click.bind(this);
      }
      click(){
        console.log(`hello ${this.name}`);
      }
    
      render(){
        return (
          <raw>
            <button onClick={this.click}>Click me</button>
          </raw>
        );
      }
    }
    
  4. 组件中条件渲染

    class LoginControl extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isLoggedIn: false
        };
      }
    
      render() {
        const { isLoggedIn } = this.state;
        // 根据isLoggedIn的值,指定渲染某个按钮。
        const button = isLoggedIn ?
              <button onClick={() => { this.setState({isLoggedIn: false}); }}>注销</button>
              : <button onClick={() => { this.setState({isLoggedIn: true}); }}>登录</button>;
    
        return (
          <div>
            <h1>
              {
                isLoggedIn ? 'Welcome back!' : 'Please sign up.'
              }
            </h1>
            {button}
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <LoginControl />,
      document.getElementById('root')
    );
    
  5. 列表循环

    • key 是一个字符串,并且在该列表中唯一
    • key 的值只是给 React 起到类似暗示的作用,不会真正的传递给 dom, 方便react更新页面,所以如果你需要使用 key 的值,应使用一个其它变量传递该值
    const data = [1, 2, 3, 4, 5];
    const listItems = data.map((item) =>
      <li key={number.toString()}>{item}</li>
    );
    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );
    
  6. 组件中表单:不同于vue,要自己写表单监听事件去动态修改绑定在表单上变量的值。

    class Reservation extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isGoing: true,
          numberOfGuests: 2
        };
        
        this.handleInputChange = this.handleInputChange.bind(this);
      }
      // 根据绑定在表单的name去动态修改指定name表单的变量值。
      handleInputChange(event) {
        const { target } = event;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const { name } = target;
        this.setState({
          [name]: value
        });
      }
      render() {
        return (
          <form>
            <label>
              Is going:
              <input
                name="isGoing"  //要跟绑定在表单的state.isGoing同名,才能动态修改绑定表单的变量值
                type="checkbox"
                checked={this.state.isGoing}
                onChange={this.handleInputChange} />
            </label>
            <br />
            <label>
              Number of guests:
              <input
                name="numberOfGuests"
                type="number"s
                value={this.state.numberOfGuests}
                onChange={this.handleInputChange} />
            </label>
          </form>
        );
      }
    }
    
  7. 状态提升(父子组件通讯):多个组件需要共享的状态提升到它们最近的父组件state上,共享的状态,跟修改共享状态的方法一起通过props分发给各个子组件,在子组件使用父组件上的共享状态。

    //1.在父组件中定义共享状态content,并将其传给各个子组件。
    class AllInput extends React.Component {
        constructor(props) {
            super(props)
            // 在父组件中添加 state 对象,用于保存数据
            this.state = { content: '' }
            this.handleContentChange = this.handleContentChange.bind(this)
        }
        
        // 定义修改 state 的方法,通过 props 传递给子组件使用
        // 接收一个参数(新的数据)
        handleContentChange(newContent) {
            this.setState({ content: newContent })
        }
        
        render() {
            // 通过 props 将 state 和修改 state 的方法都传递给子组件
            return (
                <div>
                	<Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                    <br /><br />
                    <Input content={ this.state.content } onContentChange={ this.handleContentChange }/>
                </div>
            )
        }
    }
    
    //2.子组件中使用父组件传来的共享状态content,跟修改content的函数
    class Input extends React.Component {
        constructor(props) {
            super(props)
            // 数据可以不再保存在子组件的 state 当中
            this.handleChange = this.handleChange.bind(this)
        }
        handleChange(e) {
            // 通过 props 获取父组件的 setState(修改数据的方法)
            this.props.onContentChange(e.target.value)
        }
    
        render() {
            // 通过 props 获取父组件的 state(数据)
            return (
                <input type='text' value={ this.props.content } onChange={ this.handleChange } />
            )
        }
    }
    
    

二、React 高级特性(1)

  • 函数组件,非受控组件,Portals,context,异步组件,性能优化,高阶组件HOC,Render Props

1. 函数组件。

  • 纯函数,输入props,输出JSX

  • 没有实例,没有生命周期,没有state

  • 不能扩展其他方法

    // 函数组件
    function List(props) {
       const {list} = this.props;
      return <ul>{list.map((item, index) => {
        return <li key={item.id}>
                <span>{item.title}</span>
               </li>
      })}</ul>
    }
    

2.非受控组件

  • ref

  • defaultValue defaultChecked

  • 手动操作DOM元素

    // 非受控组件, 输入框的值不会影响到state的值,state的值只是用来初始化input的默认值。
    class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            name: "jiangyf",
            flag: true
          }
          this.nameInputRef = React.creatRef();  //创建ref
        }
        render() {
          return <div>
               // 使用defaultValue,而不是value
               <input defaultValue={this.state.name} ref={this.nameInputRef}>
               <button onClick={this.alertName}></button>
            </div>
        }
        alertName = () => {
            const elem = this.nameInputRef.current; //通过 ref 获取 Dom 节点
            alert(elem.value)  // 不是this.state.name
        } 
      
    }
    
    // 受控组件
    <input value={this.state.name} onChange={this.onInputChange}></input>
    onInputChange = (e)=> {
      this.setState({
        name: e.target.value
      })
    }
    
  • 非受控组件使用场景

    • 必须手动操作Dom元素,setState实现不了
    • 文件上传
    • 某些富文本编辑器,要传入DOM元素

3. Portals

  • 可以把组件渲染到指定节点中,可以让组件渲染到父组件以外层级

    export default class Portals extends Component {
        render() {
          return (
             <div title='我是父组件'>
                <p>我想出现在root中</p>
                <Test/>
             <div>
          )
        }
    }
    
    function Test() {
       return ReactDom.createPortal(
          <ChildA/>,
         document.getElementById("container");
       )
    }
    
    function ChildA() {
       return <p>我是childA</p>;
    }
    
    // 渲染结果
    <div id="root"> 
       <div title='我是父组件'>
           <p>我想出现在root中</p>
       <div>
       <div id="container">
           <p>我是childA</p>
       </div>
    </div>
    

4.context

  • 场景:公共信息(语音,主题)如何传递给每个组件?

  • 用props太繁琐

  • 用redux小题大做

    // 1.创建Context 填入默认值(任何一个 js 变量)
    const ThemeContext = React.createContext("light");
    
    
    class TestApp extentds React.Component {
      constructor(props) {
        super(props);
        this.state = {
          theme: "light"
        }
      }
      
      render() {
        // 2. 生产context:ThemeContext.Provider标签的value提供Context内容
        return <ThemeContext.Provider value={this.state.theme}> 
            <Toolbar></Toolbar>
            <button onClick={this.changeTheme}></button>
        </ThemeContext.Provider>
      }
      
      // 修改 context内容
      changeTheme = () => {
        this.setState({
          theme: this.state.theme == 'light' ? 'dark' : 'light'
        })
      }
    }
    
    function ToolBar(props) {
      return (
        <div>
          <ThemeButton></ThemeButton>
          <ThemeLink></ThemeLink>
        </div>
      )
    }
    
    // 3. class组件如何使用context?
    class ThemedButton extentds React.Component {
      render() {
        // react 会往上找到最近的ThemeContext.Provider中的value值。
        const theme = this.context;
        return <div>
           <p>button theme is {theme}</p>
        </div>
      }
    }
    // 指定class组件静态属性contextType 读取当前的 ThemeContext.
    ThemedButton.contextType = ThemeContext;
    
    
    // 4. 函数组件如何使用context?
    function ThemeLink(props) {
      // 函数组件可以用Consumer,用this.context会报错,因为没有实例。
      return <ThemeContext.Consumer>
        {value => <p>link theme is {value}</p>}
      </ThemeContext.Consumer>
    }
    
  

###     5.react如何异步加载组件

* ```react
  const  ContextDemo = React.lazy(() => import("./ContextDemo"));
  
  class TestApp extends React.Component {
    constructor(props) {
      super(props);
    }
    
    reder() {
      // 异步加载组件必须配合 <React.Suspense fallback={}></React.Suspense>一起使用
      return <div>
         <React.Suspense fallback={<div>Loading</div>}>
           <ContextDemo/>
        </React.Suspense>   
      </div>
    }
  }

三、React 高级特性(2)

1. 性能优化-SCU

  • react 父组件有更新,子组件则无条件也更新,如有需要可通过SCU优化。
  • SCU 需要的时候才优化
  1. SCU基本用法,默认返回 true,即默认重新渲染所有子组件。

    shouldComponentUpdate(nextProps, nextState) {
      if(nextState.count !== this.state.count) {
        return true; // 可以渲染
      } 
      return false; // 不重复渲染
    }
    
  2. SCU 一定要配合 不可变值 使用

    import _ from 'lodash';
    
    class TodoListDemo extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                list: [
                    { id: 'id-1', title: '标题1'},
                    { id: 'id-2', title: '标题2'},]
            }
        }
        render() {
            return <div>
                <Input submitTitle={this.onSubmitTitle}/>
                <List list={this.state.list}/>
            </div>
        }
        onSubmitTitle = (title) => {
            // 正确的用法
            this.setState({
                list: this.state.list.concat({
                    id: `id-${Date.now()}`,
                    title
                })
            })
    
            // 错误用法,这样写会导致shouldComponentUpdate取到的nextProps.list 跟 this.props.list 一样导致无法重新渲染。
            // this.state.list.push({
            //     id: `id-${Date.now()}`,
            //     title
            // })
            // this.setState({
            //     list: this.state.list
            // })
        }
    }
    
    
    class List extends React.Component {
        constructor(props) {
            super(props)
        }
        render() {
            const { list } = this.props
    
            return <ul>{list.map((item, index) => {
                return <li key={item.id}>
                    <span>{item.title}</span>
                </li>
            })}</ul>
        }
    
        // 增加 shouldComponentUpdate
        shouldComponentUpdate(nextProps, nextState) {
            // _.isEqual 做对象或者数组的深度比较(一次性递归到底)
            if (_.isEqual(nextProps.list, this.props.list)) {
                // 相等,则不重复渲染
                return false
            }
            return true // 不相等,则渲染
        }
    }
    

2. 性能优化-PureComponent 和 memo 浅比较,实现组件是否重新渲染。

  • PureComponent跟memo是浅比较。
  • React.PureComponent是基于浅比较,所以只要属性值是引用类型,但是修改后的值变了,但是地址不变,也不会重新渲染。
  • 浅比较已经适用大部分情况(尽量不要做深度比较)。
  1. React.PureComponent基本用法

    class List extends React.PureComponent {
        constructor(props) {
            super(props)
        }
        render() {
            const { list } = this.props
              
            // 如果title跟id没有改变的话就不会重写渲染
            return <ul>{list.map((item, index) => {
                return <li key={item.id}>
                    <span>{item.title}</span>
                </li>
            })}</ul>
        }
    
        //  PureComponent 里有 shouldComponentUpdate 函数的话,直接使用 shouldComponentUpdate 的结果作为是否更新的依据,没有 shouldComponentUpdate 函数的话,才会去判断是不是 PureComponent ,是的话再去做 shallowEqual 浅比较。
    }
    
  2. React.memo基本用法

    // 函数组件
    function MyComponent(props) {
    }
    // 编写类似SCU的函数,用来处理是否重新渲染
    function areEqual(prevProps, nextProps) {
    }
    // 将函数组件,类似SCU函数一起传入React.mome,生成新的函数组件
    export default React.memo(MyComponent, areEqual);
    

3. 性能优化-Immutable.js

  • 彻底拥抱“不可变值”

  • 基于共享数据(不是深拷贝),速度好

  • 有一定学习和迁移成本,按需使用

    const map1 = Immutable.map({ a: 1, b: 2, c: 3});
    const map2 = Immutable.set( "b", 50);
    map1.get("b");  // 2
    map2.get("b");  // 50
    

4. 高阶组件

  1. 基本用法

    // 高阶组件不是一种功能,而不是一种模式
    const HOCFactory = (Component) => {
      class  HOC extends React.Component {
        // 在这个类内部定义多个组件的公共逻辑
        
        render() {
          // 将处理好的数据传入到各个组件中各自渲染
          return <Component {...this.props}/> 
        }
      }
      return HOC
    }
    const TestComponent1 = HOCFactory(WrappedComponent1);
    const TestComponent2 = HOCFactory(WrappedComponent2);
    
  2. 例:利用高阶组件公用一份鼠标坐标信息,渲染出不同的展示效果。

    const withMouse = (Component) => {
      class withMouseComponent extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            x: 0,
            y: 0
          }
        }
        // 获取鼠标信息公共逻辑
        getMouseInfos = (e) => {
          this.setState({
            x: e.clientX,
            y: e.clientY
          })
        }
        render() {
          return (
             <div onMouseMove={this.getMouseInfos}>
              {/* 将获取到的鼠标信息,跟传入到高阶组价中的所有数据都传到各个组件中渲染 */}
               <Component {...this.props} mouse={this.state}></Component>
             </div>
          )
        }
      }
      return withMouseComponent;
    }
    
    
    const App = (props) => {
        const a = props.a
        const { x, y } = props.mouse // 接收 mouse 属性
        return (
            <div style={{ height: '500px' }}>
                <h1>The mouse position is ({x}, {y})</h1>
                <p>{a}</p>
            </div>
        )
    }
    
    export default withMouse(App) // 返回高阶函数
    
    
    
    
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 智慧社区背景与挑战 随着城市化的快速发展,社区面临健康、安全、邻里关系和服务质量等多方面的挑战。华为技术有限公司提出智慧社区解决方案,旨在通过先进的数字化技术应对这些问题,提升城市社区的生活质量。 2. 技术推动智慧社区发展 技术进步,特别是数字化、无线化、移动化和物联化,为城市社区的智慧化提供了可能。这些技术的应用不仅提高了社区的运行效率,也增强了居民的便利性和安全性。 3. 智慧社区的核心价值 智慧社区承载了智慧城市的核心价值,通过全面信息化处理,实现对城市各个方面的数字网络化管理、服务与决策功能,从而提升社会服务效率,整合社会服务资源。 4. 多层次、全方位的智慧社区服务 智慧社区通过构建和谐、温情、平安和健康四大社区模块,满足社区居民的多层次需求。这些服务模块包括社区医疗、安全监控、情感沟通和健康监测等。 5. 智慧社区技术框架 智慧社区技术框架强调统一平台的建设,设立数据中心,构建基础网络,并通过分层建设,实现平台能力及应用的可持续成长和扩展。 6. 感知统一平台与服务方案 感知统一平台是智慧社区的关键组成部分,通过统一的RFID身份识别和信息管理,实现社区服务的智能化和便捷化。同时,提供社区内外监控、紧急救助服务和便民服务等。 7. 健康社区的构建 健康社区模块专注于为居民提供健康管理服务,通过整合医疗资源和居民接入,实现远程医疗、慢性病管理和紧急救助等功能,推动医疗模式从治疗向预防转变。 8. 平安社区的安全保障 平安社区通过闭路电视监控、防盗报警和紧急求助等技术,保障社区居民的人身和财产安全,实现社区环境的实时监控和智能分析。 9. 温情社区的情感沟通 温情社区着重于建立社区居民间的情感联系,通过组织社区活动、一键呼叫服务和互帮互助平台,增强邻里间的交流和互助。 10. 和谐社区的资源整合 和谐社区作为社会资源的整合协调者,通过统一接入和身份识别,实现社区信息和服务的便捷获取,提升居民生活质量,促进社区和谐。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值