React基础

一、jsx语法规则

jsx语法规则:

  1.  定义虚拟DOM时,不要写引号
  2.  标签中混入JS表达式要用{}
  3.  样式的类名指定不要用class,要用className
  4.  内联样式,要用styles={{key:value的样式去写}}
  5.  只有一个跟标签
  6.  标签需要闭合
  7.  标签首字母

       (1)若小写字母开头,则将标签转为html中同名元素,若html中无该标签对应的同名元素,则报错

       (2)若大写字母开头,react就去渲染对应的组件,若组件没有定义,就报错

二、函数式组件

在没有脚手架的情况下,需要引入相关的react的包

React相关的文件:

react.development.js —— React核心文件
react-dom.development.js —— React用来操作DOM的文件
babel.min.js —— 在React中会使用到jsx,但是浏览器不支持jsx,所以使用babel将jsx编译为js

<!--引入react核心库 核心库必须最先引入-->
<script type="text/javascript" src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--引入react拓展库,react-dom,支持react操作dom-->
<script type="text/javascript" src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!--引入babel,用于将jsx转换为js-->
<script type="text/javascript" src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<div id="test"></div>
<!-- // 引入核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- // 用于支持DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- // 引入babel 将jsx转换成js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
  // 创建函数式组件
  function MyComponent () {
    return <h2>我是函数式组件定义的㢟(简单组件)的定义</h2>
  }
  // 渲染组件到页面
  ReactDOM.render(<MyComponent/>, document.getElementById('test'))
</script>
三、类组件
<div id="test"></div>
<!-- // 引入核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- // 用于支持DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- // 引入babel 将jsx转换成js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
  // 创建类式组件
  class MyComponent extends React.Component{
  // render 放在类的原型对象上,供实例使用,this指的是MyComponent组件的实例对象
    render() {
      return (
        <h2>我是类组件</h2>
      )
    }
  }
  // 渲染组件到页面
  ReactDOM.render(<MyComponent/>, document.getElementById('test'))
/*
  执行了ReactDOM.render(<MyComponent/>...)之后,发生了什么
  1.React解析组件标签,找到MyComponent组件
  2.发现组件是使用类定义的,随后new出来该类的实例,是通过该实例调用到原型上的render方法
  3.将render返回的虚拟DOM转化为真是DOM,随后呈现在页面中
*/
四、组件三大核心属性

1.state

  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">
   // 创建类式组件
   class Weather extends React.Component{
     // 构造器调用一次
     constructor (props) {
      super(props)
      this.state = {
        isHot: true
      }
      this.changeWeather = this.changeWeather.bind(this)
     }
     
     // render调用1+n次  1是初始化那次,n是状态更新的次数
     render() {
      const {isHot} = this.state
      return (
        <h2 onClick={this.changeWeather}>今天天气很{isHot ?  '炎热': '凉爽'}</h2>
      )
     }
     changeWeather () {
      // changeWeather放在那里?Weather的原型对象上,供实例使用
      // 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用的
      // 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined

      // this.state.isHot = !this.state.isHot(错误写法)

      // 状态(state)不可直接更改,必须通过setState修改,且更新是一种合并,不是合并
      this.setState({
        isHot: !this.state.isHot
      })
     }
   }
    // 渲染组件到页面
    ReactDOM.render(<Weather/>, document.getElementById('test'))
  </script>

state简写方式:

  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">
   // 创建类式组件
   class Weather extends React.Component{
     state = {
      isHot: true
     }
     render() {
      const {isHot} = this.state
      return (
        <h2 onClick={this.changeWeather}>今天天气很{isHot ?  '炎热': '凉爽'}</h2>
      )
     }
     // 自定义方法-要用赋值语句的形式+箭头函数 
     changeWeather = () => {
      this.setState({
        isHot: !this.state.isHot
      })
     }
   }
    // 渲染组件到页面
    ReactDOM.render(<Weather/>, document.getElementById('test'))
  </script>

2.props

构造器是否接受props,是否传递给super,取决于是否希望在构造器中通过this访问props

  <div id="test1"></div>
  <div id="test2"></div>
  <div id="test3"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/javascript" src="../js/prop-types.js"></script>
  <!-- PropTypes -->
  <script type="text/babel">
   // 创建类式组件
   class Person extends React.Component{
      // props做限制
      
      render () { 
        const {name, age, sex} = this.props
        // prop是只读的
        return (
          <ul>
            <li>姓名: {name}</li>
            <li>性别:{sex}</li>
            <li>年龄: {age+1}</li>
          </ul>
        )
      }
   }
   // 对标签属性进行类型,必要性的限制
   Person.propTypes = {
    name: PropTypes.string.isRequired, // 限制name必传,且为字符串
    sex: PropTypes.string, // 限制sex为字符串
    age: PropTypes.number, // 限制age为数值
    speak: PropTypes.func // 限制speak为函数
   }
  //  指定默认标签属性
   Person.defaults = {
    sex: '不男不女',
    age: 18
   }
    // 渲染组件到页面,单传递
    ReactDOM.render(<Person name="jerry" speak='2' age={19} sex="女"/>, document.getElementById('test1'))
    ReactDOM.render(<Person name="tom" age={18} sex="女"/>, document.getElementById('test2'))
    // ReactDOM.render(<Person name="laowang" age="18" sex="女"/>, document.getElementById('test3'))
    // 多传递
    const p = {name: 'laowang', age: 18, sex: '女'}
    // 因为babel以及React库,所以可以直接使用...p,不然对于对象会报错
    ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))
  </script>

简写props,将类外的移到类内,并且在险种语句前面加static

  <div id="test1"></div>
  <div id="test2"></div>
  <div id="test3"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/javascript" src="../js/prop-types.js"></script>
  <!-- PropTypes -->
  <script type="text/babel">
   // 创建类式组件
   class Person extends React.Component{
      // 对标强属性进行类型,必要性的限制
      static propTypes = {
        name: PropTypes.string.isRequired, // 限制name必传,且为字符串
        sex: PropTypes.string, // 限制sex为字符串
        age: PropTypes.number, // 限制age为数值
        speak: PropTypes.func // 限制speak为函数
      }
      //  指定默认标签属性
      static defaults = {
        sex: '不男不女',
        age: 18
      }
      render () { 
        const {name, age, sex} = this.props
        // prop是只读的
        return (
          <ul>
            <li>姓名: {name}</li>
            <li>性别:{sex}</li>
            <li>年龄: {age+1}</li>
          </ul>
        )
      }
    }
    // 渲染组件到页面,单传递
    ReactDOM.render(<Person name="jerry" speak='2' age={19} sex="女"/>, document.getElementById('test1'))
    ReactDOM.render(<Person name="tom" age={18} sex="女"/>, document.getElementById('test2'))
    // ReactDOM.render(<Person name="laowang" age="18" sex="女"/>, document.getElementById('test3'))
    // 多传递
    const p = {name: 'laowang', age: 18, sex: '女'}
    // 因为babel以及React库,所以可以直接使用...p,不然对于对象会报错
    ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))
  </script>

函数式组件使用props

    // 函数式组件使用props
    function Person (props) {
      const {name, age, sex} = props
      return (
        <ul>
          <li>姓名: {name}</li>
          <li>性别:{sex}</li>
          <li>年龄: {age+1}</li>
        </ul>
      )
    }

3.refs与数据处理

  <div id="test1"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/javascript" src="../js/prop-types.js"></script>
  <!-- PropTypes -->
  <script type="text/babel">
    /*
      事件处理函数
     (1)通过onXXX属性指定事件处理函数, 注意大小写
        React使用的是自定义(合成)事件,而不是使用的原生DOM事件  为了更好的兼容性
        React是通过事件委托的方式处理的 为了高效
     (2)通过event.target得到发生事件的DOM元素对象
    */

    // refs
    // 创建类式组件
    class Person extends React.Component{
      // 这种情况可能会弃用,直接使用refs
      showData = () => {
        // 第一种
        // const {input1} = this.refs
        // 第二种
        const {input1} = this
      }
      showData2 = () => {
        // 第一种
        // const {input2} = this.refs
        // 第二种
        const {input2} = this
      }
      saveInput =(a) => {
        this.input1 = a
      }
      // 回调函数式的ref 
      // 创建Refs
      /*  调用后可以返回一个容器。该容器可以存储呗ref所表示的节点
      */
      myRef = React.createRef()
      showData1 =() => {
        alert(this.myRef.current.value)
      }
      render () { 
        return (
          <div>
            {/*// 第一种*/}
            <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
            {/*第二种 回调函数中执行的次数,初始化调取一次, 更新的时候每次会调取两次,这种较常用*/} 
            {/*<input ref={(currentNode) => {this.input1 = currentNode}} type="text" placeholder="点击按钮提示数据"/>*/}
            {/*这种避免调用两次*/}
            {/*<input ref={this.saveInput} type="text" placeholder="点击按钮提示数据"/>*/}
            {/*// 第三种*/}
            <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
            {/*<button onClick={this.showData}>点我提示左侧数据</button>*/}
            <button onClick={this.showData1}>点我提示左侧数据</button>
            {/*<input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点提示数据"/>*/}
            <input onBlur={this.showData2} ref={c => {this.input2 = c}} type="text" placeholder="失去焦点提示数据"/>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Person/>, document.getElementById('test1'))
  </script>

五、受控组件与非受控组件

  <div id="test1"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/javascript" src="../js/prop-types.js"></script>
  <!-- PropTypes -->
  <script type="text/babel">
    class Login extends React.Component{
      handleSubmit = (event) => {
        // 阻止默认事件,不让其自动刷新
        event.preventDefault()
        // const {username, password } = this
        // alert("用户名是"+username.value+"密码是:"+password.value)
      }
      state={
        username: '',
        password: ''
      }
      saveUsername = (event) => {
        this.setState({
          username:event.target.value
        })
      }
      savePassword = (event) => {
        this.setState({
          password:event.target.value
        })
      }

      /*
        高阶函数:如果一个函数符合下面两个规范中的任何一个,那该函数就是高阶函数
        1.若A函数,接受的参数是一个函数,那么A就可以称之为高阶函数
        2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
        常见的高阶函数:Promise、定时器

        函数柯里化:通过函数调用继续返回函数的方式,实现多次接受参数最后统一处理的函数编码形式
        function sum(a) {
          return (b) => {
            return (c) => {
              return a+b+c
            }
          }
        }
        sum(1)(2)(3)
      */
      // 保存表单数据到状态中
      saveFormData = (dataType) => {
        return (event) => {
          console.log(event.target);
          this.setState({
            [dataType]: event.target.value
          })
        }
      }
      render () { 
        return (
          <form onSubmit={this.handleSubmit}>
            {/*输入类的属于非受控组件现用现取*/}
            {/*用户名:<input ref={c => this.username = c} type="text" name="username"/>
          密码:<input ref={c => this.password = c} type="password" name="password"/>*/}
            {/*输入类的属于需要放到state,并从state维护状态*/}
            {/*用户名:<input onChange={this.saveUsername} type="text" name="username"/>
            密码:<input onChange={this.savePassword} type="password" name="password"/>
          <button>登录</button>*/}

            {/*高阶函数,函数柯里化*/}
            用户名:<input onChange={this.saveFormData('username')} type="text" name="username"/>
            密码:<input onChange={this.saveFormData('password')} type="password" name="password"/>
            <button>登录</button>
          </form>
        )
      }
    }
    
    ReactDOM.render(<Login/>, document.getElementById('test1'))
  </script>

不使用柯里化

saveFormData = (dataType,event) => {
  this.setState({
    [dataType]: event.target.value
  })
}
render () { 
  return (
    <form onSubmit={this.handleSubmit}>
       用户名:<input onChange={(event) => {this.saveFormData('username', event.target.value)}} type="text" name="username"/>
       密码:<input onChange={(event) => {this.saveFormData('password', event.target.value)}} type="password" name="password"/>
       <button>登录</button>
    </form>
  )
}
五、生命周期

1.生命周期(旧)

 (1)引入生命周期 

想要一开始定时器就触发,但是定时器放在render()里,发生了递归,render初始化第一次调用,每修改一次state一直调用;但是如果放在action中不能一上来就开启定时器,

  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">
    class Life extends React.Component{
      state = {
        opacity: 1
      }
      detach = () => {
        // 卸载组件
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }
      // 这么做不能一上来就开启定时器,而是点击的时候才能开启定时器
      action = () => {
        // 发生了递归,render初始化第一次调用。每修改一次state一直调用
        setInterval(() => {
          // 获取原状态
          let {opacity} = this.state
          // 减小0.1
          opacity -= 0.1
          if (opacity <= 0) {
            opacity = 1
          }
          // 设置新的透明度
          this.setState({
            opacity
          })
        }, 200)
      }
      render(){
        /*// 发生了递归,render初始化第一次调用。每修改一次state一直调用
        setInterval(() => {
          // 获取原状态
          let {opacity} = this.state
          // 减小0.1
          opacity -= 0.1
          if (opacity <= 0) {
            opacity = 1
          }
          // 设置新的透明度
          this.setState({
            opacity
          })
        }, 200)
        */
        return(
          <div>
            <h1 style={{opacity:this.state.opacity}}>React学不会怎么办</h1>
            <button onClick={this.detach}>不活了</button>
            <button onClick={this.action}>开始变化</button>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Life/>, document.getElementById('test'))
  </script>

 解决上述问题

  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel"> 
    // 生命周期回调函数 《=》生命周期钩子函数=》生命周期函数=声明周期钩子
    class Life extends React.Component{
      state = {
        opacity: 1
      }
      detach = () => {
        // 清除定时器
        // clearInterval(this.timer)
        // 卸载组件
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }
      // 组件挂载完毕
      componentDidMount () {
        this.timer = setInterval(() => {
          // 获取原状态
          let {opacity} = this.state
          // 减小0.1
          opacity -= 0.1
          if (opacity <= 0) {
            opacity = 1
          }
          // 设置新的透明度
          this.setState({
            opacity
          })
        }, 200)
      }
      // 组件将要卸载
      componentWillUnmount () {
        // 清除定时器
        clearInterval(this.timer)
      }
      
      // render调用的时机,初始化渲染,状态更新之后
      render(){
        return(
          <div>
            <h1 style={{opacity:this.state.opacity}}>React学不会怎么办</h1>
            <button onClick={this.detach}>不活了</button>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Life/>, document.getElementById('test'))
  </script>

图片表示生命周期图

react版本18.0.0的需要加UNSAFE_,UNSAFE_componentWillUpdate、UNSAFE_componentWillReceiveProps、UNSAFE_componentWillMount,才能正常工作

 1.初始化阶段:由ReactDOM.render()触发 ---初次渲染

          1.constructor

          2.componentWillMount()

          3.render()

          4.componentDidMount() ===常用

            一般在这个钩子中做一些初始化的事情,比如开启定时器。发送网络请求等

   2.更新阶段:由组件内部this.setState()或父组件render触发

          1.shouldComponentUpdate()

          2.componentWillUpdate()

          3.render() ==必须使用的一个

          4.componentDidUpdate()

   3.卸载组件:由React.DOM.unmountComponentAtNode()触发

          1.componentWillUnmount()  ==常用

          一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息等

挂载时:

setState时:

forceUpdate时 

父组件render

 

   class A extends React.Component{
      state = {
        carName: '奔驰'
      }
      changeCar = () => {
        this.setState({
          carName: '奥拓'
        })
      }
      render () {
        return (
          <div>
            <div>A</div>
            <button onClick={this.changeCar}>换车</button>
            <B carName={this.state.carName}/>
          </div>
        )
      }
    }
    class B extends React.Component{
      // 组件将要接受新的props的钩子
      UNSAFE_componentWillReceiveProps(props) {
        console.log('B--componentWillReceiveProps',props);
      }
      // 组件是否被更新,更新组件的阀门
      shouldComponentUpdate() {
        console.log('B --shouldComponentUpdate');
        return true
      }
      // 组件将要更新
      UNSAFE_componentWillUpdate () {
        console.log('B --componentWillUpdate');
      }
      // 组件更新完毕的钩子
      componentDidUpdate() {
        console.log('B --componentDidUpdate')
      }
      render () {
        console.log('B--render');
        return (
          <div>我是B组件,接收到的车是:{this.props.carName}</div>
        )
      }
    }

2.生命周期(新)

 旧的和新的差别,废弃三个生命周期函数,同时提出两个新的生命周期函数

// state的值在任何的时候取决于props,那么可以使用getDerivedStateFromProps
static getDerivedStateFromProps(props,state) {
  console.log('count--getDerivedStateFromProps', props,state);
  // return props
  return null
}
// 在更新之前获取快照
getSnapshotBeforeUpdate() {
  console.log('count--getSnapshotBeforeUpdate');
  // 需要返回一个快照值不然会报警告
  return '1'
}
// 组件更新完毕的钩子
componentDidUpdate(preProps,preState,snapshotValue) {
  console.log('Count --componentDidUpdate', preProps,preState,snapshotValue)
}

getSnapshotBeforeUpdate的使用场景:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
<style>
  .list{
    width: 200px;
    height: 150px;
    background-color: skyblue;
    overflow: auto;
  }
  .news{
    height:30px;
  }
</style>
</head>
<body>
  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">
    class NewsList extends React.Component{
      state = {
        newsArr: []
      }
      componentDidMount() {
        setInterval(() => {
          // 获取原状态
          const {newsArr} = this.state
          // 模拟一条新闻
          const news = '新闻'+(newsArr.length + 1)
          // 更新状态
          this.setState({
            newsArr: [news, ...newsArr]
          })
        },1000)
      }
      getSnapshotBeforeUpdate() {
        return this.refs.list.scrollHeight
      }
      componentDidUpdate(preProps,preState,height) {
        this.refs.list.scrollTop += this.refs.list.scrollHeight - height
      }
      render () {
        return (
          <div className="list" ref="list">
           {
            this.state.newsArr.map((n,index)=> {
              return <div className="news" key={index}>{n}</div>
            })
           }
          </div>
        )
      }
    }
    ReactDOM.render(<NewsList/>, document.getElementById('test'))
  </script>
</body>
</html>
六、虚拟DOM和Diffing算法

验证diffing算法

  <div id="test"></div>
  <!-- // 引入核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- // 用于支持DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- // 引入babel 将jsx转换成js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">
    class Time extends React.Component{
      state = {
        date: new Date()
      }
      componentDidMount() {
        setInterval(() => {
          this.setState({
            date: new Date()
          })
        },1000)
      }
      render () {
        return (
          <div>
           <h1>Hello</h1>
           <input type="text"/>
           <span>现在是:{this.state.date.toTimeString()}</span>
          </div>
        )
      }
    }
    ReactDOM.render(<Time/>, document.getElementById('test'))
  </script>

1.虚拟DOM中key的作用

      当状态中的数据发生变化时,react会更具【新数据】生成【新的虚拟DOM】

      随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:

      a.旧虚拟DOM中找到了与虚拟DOM相同的key

      (1)若虚拟DOM中内容没变,直接使用之前的真实DOM

      (2)若虚拟DOM中内容变了,则生成新的真实DOM,随后持续换掉页面中之前的真实DOM

      b.旧虚拟DOM中未找到与新虚拟DOM相同的key

        根据数据创建新的真实DOM,随后渲染到页面

    2.用index作为key可能引发的问题:

      (1) 若对数据进行:逆序添加,逆序删除等破坏顺序操作

      会产生没有必要的真实DOM更新==界面效果没问题,但效率低

      (2)如果结构中还包含输入类的DOM:

      会产生错误DOM更新==界面有问题

      (3)注意:如果不存在对数据的逆序添加、删除等破坏顺序操作

      仅用于渲染列表用于展示。使用index作为key是没有问题的

    3.开发中如何选择key?

      (1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等

      (2)如果确定只是简单的展示数据,用index也是可以的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值