• React 面向组件化编程


    React 面向组件化编程

    面向对象 ----> 面向模块 ----> 面向组件

    套路:

    注意:

    组件名必须大写开头;

    只能有一个根标签;

    <input />虚拟DOM 元素必须有结束标签

    方式1. 工厂函数组件 (简单组件) ----> 只能定义无状态的组件

    • function MyComponent(){    // 只能 大写开头,区别于普通函数
          return <h2>工厂函数组件(简单组件)</h2>
      }
      
      // 渲染函数组件标签
      // 内部直接调用 工厂组件函数 得到虚拟组件函数 ReactDOM.render(
      <MyComponent/>, document.getElementById("outer"))

    方式2: ES6 类组件 (复杂组件)

    • class MyComponent2 extends React.Component {
          // 1. 必须继承
          // 2. 必须大写开头
          // 3. 必须重写 render 方法, 指定 return 返回值
          render (){
              return <h2>ES6类组件(复杂组件)</h2>
          }
      }
      
      // 渲染类组件标签
      // 内部会自动创建类的实例,并调用其 render() 方法得到需要渲染的虚拟 DOM ReactDOM.render(
      <MyComponent/>, document.getElementById("outer"));
      // 获取到虚拟 DOM 对象 页面上的 原生 DOM

    组件的三大属性:

    面试题: 区别一下组件的 props 和 state 属性

    相同点: 都是组件实例的对象,用于保存数据

    不同点:

    state 保存组件自身内部可变化的数据

    props 保存从外部传入组件内部的数据,组件内部只读而不修改

    • state 对象

    是组件对象最终要的 属性,属性值是一个对象 (可以包含多个)

    组件被称为 "状态机"

    更新状态 从而 更新界面 ----> this.setState({stateName1 : newValue})

    this.state 是组件私有的,通过调用 this.setState() 来改变它

    this.setState() 每次修改以后,自动调用 this.render 方法,再次渲染组件

    可以通过 getInitialState() 方法初始化,在组件的生命周期中仅执行一次

    • var FavoriteButton=React.createClass({
        getInitialState:function(){
          return {favorite:false};
        },
        handleClick:function(event){
          this.setState({favorite:!this.state.favorite});
        },
        render:function(){
          var text=this.state.favorite? 'favorite':'un favorite';
          return (
            <div type='button' onClick={this.handleClick}>
              You {text} this. Click to toggle.
            </div>
          );
        }
      });
      --------------------- 
      作者:CrazyCodeBoy 
      来源:CSDN 
      原文:https://blog.csdn.net/fengyuzhengfan/article/details/52185921 
      版权声明:本文为博主原创文章,转载请附上博文链接!

    当 state 更新之后,组件就会重新渲染自己。

    render() 方法依赖于 this.props 和 this.state ,

    框架会确保渲染出来的 UI 界面总是与输入( this.props 和 this.state )保持一致

    实例: iLikeQuQ

    • class Like extends React.Component {    // 组件类
          constructor(props){
              super(props)
              this.state = {isLikeMe: false}
          }
          
      // 组件中自定义的方法的 this 默认指向 undefined
      // 利用 箭头函数 没有自己的 this 来 在函数内使用 this
      // 若要 更新组件的显示,必须使用 组件的 setState() chgText
      = ()=>{ // this.state.isLikeMe = !this.state.isLikeMe 无效操作 this.setState({ isLikeMe: !this.state.isLikeMe }) } render(){ const isLikeMe = this.state.isLikeMe const text = isLikeMe?"I Like U.":"U Like Me." return <h2 onClick={this.chgText}>{text}</h2> } }
      ReactDOM.render(<Like/>, document.getElementById("outer"));

    每次点击,改变了 状态,那么就会自动重新调用 render() 方法

    props 对象

    每个组件只会根据 props 渲染了自己一次,props 是不可变的

    <script src="https://cdn.bootcss.com/prop-types/15.6.2/prop-types.js"></script>

    • class Person extends React.Component {
          /**** 默认会执行
          constructor (props){
              super(props);    // props 包含了组件标签的所有属性数据
          }
          ****/
          
          render(){
              const {name, age, sex} = this.props;
              return ({
                  <ul>
                      <li>姓名: {name}</li>
                      <li>年龄: {age}</li>
                      <li>性别: {sex}</li>
                  </ul>
              })
          }
      }
      // this.props.xxx    // 1. 读取属性名 xxx 对应的 属性值
      Person.propTypes = {    // 2. 设置 props 中属性的约束条件
          name: PropTypes.string.isRequired    // 必须传参,且 string
      }
      
      Person.defaultProps = {    // 3. 设置 props 中属性的默认值
          age: 18,
          sex: "未知"
      }
      
      /**************************************/
      const sun = {
          name: "孙悟空",
          age: 550,
          sex: "男" 
      }
      
      // name 被 isRequired 修饰,必须传,且类型必须为 string
      ReactDOM.render(<Person name={sun.name} age={sun.age} sex={sun.sex}/>, document.getElementById("outer"));
      
      // ReactDOM.render(<Person {...sun}/>, document.getElementById("outer"));    // 简化写法

    优化为: (propTypes, defaultProps , state 不需要给实例对象直接调用)

    • class Person extends React.Component {
          // 1. 给组件对象 设置 state 属性
          state = {    
              isLikeMe: false
          }
          
          // 给类添加 属性,只能 类 内部调用
          // 2. 设置 props 中属性的约束条件
          static propTypes = {    
              name: PropTypes.string.isRequired    // 必须传参,且 string
          }
          
          // 3. 设置 props 中属性的默认值
          static defaultProps = {   
              age: 18,
              sex: "未知"
           }
      
          render(){
              const {name, age, sex} = this.props;
              return ({
                  <ul>
                      <li>姓名: {name}</li>
                      <li>年龄: {age}</li>
                      <li>性别: {sex}</li>
                  </ul>
              })
          }
      }
      
      /**************************************/
      const sun = {
          name: "孙悟空",
          age: 550,
          sex: "男" 
      }
      
      // name 被 isRequired 修饰,必须传,且类型必须为 string
      ReactDOM.render(<Person {...sun}/>, document.getElementById("outer"));    // 简化写法

    refs 对象

    • // 组件对象 refs 保存的是 ref 关联的虚拟 DOM 元素
      // refs {属性: 属性值}
      // refs {ref 的值: 对应的 DOM 元素对象}
      // refs {"left": <input>元素对象}
      class MyComponent extends ReactComponent {
          hint = ()=>{
              console.log(this.refs.left.value);
          }
      
          handleBlur = (event)=>{
              // console.log(this.refs.right.value);
              console.log(event.target.value);
          }
      
          render(){
              return ({
                  <div>
                      <input type="text" ref="left"/>
                      <button onClick={this.hint}></button>
                      <input type="text" ref="right" onBlur={this.handleBlur} />
                  </div>
              })
          }
      }
      
      ReactDOM.render(<MyComponent/>, document.getElementById("oouter"))
    • 外部 向 组件对象 传入 props 的两种方式
    • 传不确定的 数据

    ReactDOM.render(<Person name={sun.name} age={sun.age} sex={sun.sex}/>, document.getElementById("outer"));

    • 传不确定的 虚拟 DOM

    传一个 虚拟 DOM 标签,组件.props.children

    传多个 虚拟 DOM 标签,组件.props.children[{...},{...}...]

    • 相关概念:

    程序: 是对现实世界的模拟

    • jsx 需要注意的地方:

    class 必须用 className 代替

    style 的属性值必须 {{"color":"red", "font-size": "16px"}}

    • 组件的事件处理方式

    1. 箭头函数的方式

    2. 初始化执行 constructor() 时,bind 绑定 this 从而产生一个新的函数,指向组件对象

    • 出现警告:

    You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

    解决:

    使用 defaultValue 代替 value

     

    • 实时显示用户输入数据

    • <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8" />
              <title>Hello React</title>
              
              <link rel="stylesheet" type="text/css" href="./css/index.css" />
          </head>
          
          <body>
              <div id="outer"></div>
              
              <!-- javascript 代码 -->
              <script src="https://cdn.bootcss.com/react/16.7.0/umd/react.development.js"></script>
              <script src="https://cdn.bootcss.com/react-dom/16.7.0/umd/react-dom.development.js"></script>
              <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.js"></script>
              <script type="text/babel">
                  class ButtonText extends React.Component {    // 组件类
                      hint = ()=>{
                          alert("left :  "+this.refs.left.value)
                      }
                      centerInfo = (event)=>{
                          this.refs.tips.innerHTML = event.target.value
                      }
                      handleBlur = (event)=>{
                          console.log("right :  "+event.target.value)
                      }
                      render(){
                          return (
                              <div>
                                  <div>
                                      <label>
                                          <input type="text" ref="left" defaultValue="Come on!"/>
                                      </label>
                                      <label>
                                          <input type="text" ref="center" onKeyUp={this.centerInfo}/>
                                      </label>
                                      <label>
                                          <input type="text" ref="right" onBlur={this.handleBlur}/>
                                      </label>
                                  </div>
                                  <button onClick={this.hint}>Tips</button>
                                  <p ref="tips">Hello there.</p>
                              </div>
                          )
                      }
                  }
                  
                  ReactDOM.render(<ButtonText/>, document.getElementById("outer"));
              </script>
          </body>
      </html>

    代码地址 : kiss me.

    问题: 在 create-react-app 之后的项目,进行 npm run build 时,发现是 用了 "/" 绝对路径,以致于找不到路径

    解决: 找到 node_modules/react-scripts/config/paths.js 第 45 行修改 "/" 为 "./"

    个人 './' 与 '/' 愚见,觉得 './' 更好,为什么官方设计是 /这样的绝对路径呢?

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    Codeforces 754A Lesha and array splitting (搜索)
    浅入分析Linux
    MakeFile基本使用
    Mac 安装YCM
    Homebrew 配置
    虚拟机复制操作CentOS6导致eth0转为eth0以至于网络服务启动失败的解决方案
    Kickstart安装
    Linux编译安装MySQL
    Python源码读后小结
    编译原理小结
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/10238239.html
Copyright © 2020-2023  润新知