React.js基础精讲(2)

react的一些语法总结

JSX语法细节补充

  • JSX是一种JavaScript语法扩展,它允许在JavaScript代码中编写类似HTML的标记。

注释语句

  • 在JSX中写注释相当于写js语句,所以一样需要{}将注释括起来。
  • 第一种注释语法很好理解,但是第二种注释语法需要注意:必须换行,否则结尾的花括号会被注释以至于无法包裹注释语句。
  • 第一种注释语法:
    1
    {/*注释语句*/}
  • 第二种注释语法:必须换行,否则结尾的花括号会被注释以至于无法包裹注释语句。
    1
    2
    3
    {
    //注释语句
    }
    react两种注释语法

外联CSS样式表及其注意事项

引入外联样式表的方法

  1. 在src下新建样式表style.css并给input设置红色边框的样式
  2. 在组件页面TodoList.js顶部引入样式表import "./style.css"即可

用className代替class

  • react中会混淆 标签样式定义类class 与 组件class TodoList extends Component{}中的class,给标签定义样式类名时使用class虽然不会报错,但控制台会提示警告:
    1
    2
    3
    4
    5
    <input
    class = "input"
    value = { this.state.inputValue }
    onChange = { this.handleInputChange.bind(this) }
    />
  • 所以我们在定义样式表class名称时需要使用className代替class:
    1
    2
    3
    4
    5
    <input
    class = "input"
    value = { this.state.inputValue }
    onChange = { this.handleInputChange.bind(this) }
    />
    使用className代替class后

dangerouslySetInnerHTML使JSX中html标签正常转译

  • 如果在JSX中希望html标签内容被识别使用可使用 dangerouslySetInnerHTML(也就是希望输入框中输入的html标签可以被识别使用)
  • 虽然这样做存在被XSS攻击的可能,但有时候也需要这样不转译的设置页面内容的情况。
  • 例子:
    • 原代码
      1
      2
      3
      4
      5
      6
      <li
      key = { index }
      onClick = { this.handleItemDelete.bind(this, index) }
      >
      { item }
      </li>
    • 使用 dangerouslySetInnerHTML:
      1
      2
      3
      4
      5
      6
      <li
      key = { index }
      onClick = { this.handleItemDelete.bind(this, index) }
      dangerouslySetInnerHTML = { {__html: item} }
      >
      </li>
      使用dangerouslySetInnerHTML前后效果
  • __html属性设置的是需要不转译显示在页面上的内容,例子这里设置为当前item,则li标签中间的{item}key省去(外层{}是代表里面写的是js表达式,内层{}代表是个js对象

htmlFor代替属性for

  • 在react中,会混淆 元素标签的for属性 与 for循环,使用 for属性 会报出警告提示,所以我们需要属性for时应**使用htmlFor代替属性for**。
  • 例子:
    • <label>中使用 for属性 使点击 “输入内容” 时鼠标自动聚焦于输入框内时,使用 for属性 :
      1
      2
      3
      4
      5
      6
      7
      <label for = "inserArea">输入内容</label>
      <input
      id = "inserArea"
      className = "input"
      value = { this.state.inputValue }
      onChange = { this.handleInputChange.bind(this) }
      />
    • **使用htmlFor代替属性for**:<label htmlFor = "inserArea">输入内容</label>
      使用htmlFor属性与for的区别

组件拆分 与 组件之间的传值

  • 总结
    • 在render函数中的js表达式中return()括号中只允许存在1个最外层标签,否则报错。也就是说所有标签都必须包含在1个父元素下。
      • 可以参考下方“父组件向子组件传递数据”的例子
      • 注意:return()中的jsx注释也像一个子元素,不能有多个根元素!
        • 例子:两种注释方法都行
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          return (
          // 这是一个注释
          <div>
          <h1>Hello, World!</h1>
          </div>
          );

          return (
          <div>
          {/* 这是一个注释 */}
          <h1>Hello, World!</h1>
          </div>
          );
  • 自定义组件名首字母大写
  • 定义组件后不要忘记在js文件最后export default 组件名;,一定要导出组件它才能在外部被引用
  • 组件的使用方式和JSX元素标签的使用方式类似
    • 比如:自定义子组件为TodoItem,在父组件TodoList的return()中可通过<TodoItem />来引用
      • 不要忘记在父组件TodoList顶部引入子组件
  • 在JSX中想要使用变量或者js表达式时必须用{}括起来,参数与属性名则不需要
    • 比如:“父组件向子组件传递数据”的例子中TodoList.js中的<TodoItem content={item} />,item就是变量,必须用{}括起来
  • 绑定事件函数前要记得到组件的构造函数中使用bind()绑定this指向,否则绑定事件函数的方法内部的this会丢失指向。
  • 在父组件内通过在子组件标签上添加属性的方式数据或者方法传给子组件。属性名是自定义的,属性值为需要传递的数据或者方法,注意 数据变量 与 方法 都需要{}括起来, 方法 不要忘记this.方法名
    • 方法名前的this千万不要漏!
  • 子组件如果想要调用父组件的方法,在父组件中通过属性传递该方法前必须先通过bind()绑定该方法内的this永远指向父组件,否则报错。因为传过去后this变为子组件,从而没有办法实现在子组件内调用父组件方法修改父组件state的效果。
    • 可参考下方“子组件向父组件传递数据”中例子

组件拆分

  • 网页可拆分为多个不同的父组件与子组件,子组件又可以嵌套其他的子组件形成树形结构。
  • 原本我们把列表的 增加 和 删除 功能都写在 TodoList.js 中,现在我们把列表中的子项放在 子组件TodoItem.js 中,增加 和 删除 功能的逻辑写在 父组件TodoList.js 中,最后再在 TodoList.js 中调用 子组件TodoItem.js来展示,触发子组件点击事件时调用父组件的方法进行删除 。

组件之间的传值

  • 往列表中增加数据
    1. 父组件TodoList通过标签的形式引用子组件并以属性的方式将数据item传给子组件TodoItem(<TodoItem content={item}>
    2. 子组件内通过{this.props.属性名}来获取从父组件传递过来的数据(对应属性值)。
  • 点击子项后删除子项
    • 原本处理逻辑是写在TodoList.js的<li>标签上的onClick事件绑定函数handleItemDelete上的,现在组件化后去掉了<li>标签,但我们可以让子组件调用父组件的handleItemDelete方法来实现改功能。
    1. 在父组件中通过 子组件属性 的方式将 数据item 、 数组下标index 、方法handleItemDelete 都传递到子组件中
    2. 子组件中,点击子组件时触动onClick事件绑定的函数handelClick,在函数handelClick内 将父组件传递过来的index值作为参数 通过属性名的方式调用父组件的deleteItem方法(即父组件的handleItemDelete方法)完成点击数据即删除的功能。

父组件向子组件传递数据(或方法)

  • 父组件通过类似html标签的方式引用子组件,同时使用在子组件标签上添加属性的方式将数据传给子组件(属性名是自定义的,属性值为需要传递的数据)注意数据变量与方法都需要{}括起来(也就是属性值需要{}括起来),方法不要忘记this.方法名
  • 子组件内需要使用父组件传递过来的数据的位置通过{this.props.属性名}来接受对应属性值(数据)
    注意:父组件向子组件传递方法时,必须在父组件中通过属性传递该方法的同时通过bind()绑定该方法的this永远指向父组件,否则报错。因为通过this.方法名传过去后this变为子组件,而子组件中并无该方法。在父组件中通过属性传递该方法时必须先通过bind()绑定该方法的this永远指向父组件,否则报错。因为通过this.方法名传过去后this变为子组件,而子组件中并无该方法。(可参考下方“子组件向父组件传递数据”中例子)
  • 例子
    • 点击按钮以后希望列表中显示输入框中内容则需要父组件将数据传给子组件,也就是 父组件TodoList 将输入框中得到的 item数据 传给 子组件TodoItem父组件向子组件传递数据(或方法)例子

子组件向父组件传递数据(子组件如何调用父组件的方法修改父组件的数据)

  • 父组件中通过属性的方式将 数据item 、 数组下标index 、方法handleItemDelete 都传递到子组件中
    • 注意:在父组件中将handleItemDelete传给子组件之前必须使用bind绑定this永远指向父组件,否则在子组件中调用this.props.deleteItem时实际上相当于调用this.handleItemDelete,但在子组件中this指向子组件,子组件中并没有handleItemDelete函数,因此报错。
  • 子组件中,点击子组件时触动onClick事件绑定的函数handelClick,在函数handelClick内 将父组件传递过来的index值作为参数 通过属性名调用父组件的deleteItem方法(即父组件的handleItemDelete方法)完成点击数据即删除的功能
    • 需要修改state数据的方法可以保留在父组件中,在子组件中通过调用父组件方法来修改数据。

子组件如何调用父组件的方法修改父组件的数据例子


,