React学习记录

托webpack的福,我终于可以开始写React了。==ORZ

我感觉我接近webpack工程师更进一步了哈哈哈。

http://huziketang.com/books/react/lesson1


http://huziketang.com/books/react/lesson1


参考文档:

1.React官网

2.react组件生命周期

特别注意(不定时更新,越往上越新):

  • 今天学到了小书的第三阶段中的context,应该算是前面学的变量不断提升到store的使用的过渡吧,之前入门过vuex,想必这里不会很难?关于这个context也是非常有趣,React团队觉得它危险,所以将它的使用设定的比较麻烦,如果不按照其章程写,它就不给你显示,哈哈,也是很符合人性化啊。以下只放部分代码,Title是在Header组件中的,内容都是小书的,比较简单:http://huziketang.com/books/react/lesson29

    下方这个是不显示的。

class Index extends Component {
        static childContextTypes = {
                themeColor: PropTypes.string
        }
        constructor() {
                super();
                this.state = {
                        themeColor: 'red'
                }
        }
        getChildContext() {
                return {
                        themeColor: this.state.themeColor
                }
        }
        render() {
                return (<div>
                        <Header />
                        <Main />
                </div>)
        }
}
class Title extends Component {
        render() {
                return (<div><h1 style={{color:this.context.themeColor}}>React.js 小标题</h1></div>)
        }
}

子组件想要获取context的内容,就必须写contextTypes(以下是写在Title中的示例) ,写完之后就能看见红色的效果了~

static contextTypes = {
                themeColor: PropTypes.string
        }
  • 今天写小书的评论组件的时候,又忘了一件事情,还是清楚定时器的问题,这次完成的是一个删除的功能,因为之前还完成了一个关于显示评论在几秒之前出现的功能,用到了计时器,所以这次在删除之后,忘了关闭计时器,而由于这个时候被删除的组件还在不断的setState,由于setState只能在挂载的组件中使用,所以它会一直报错。

  • 此句来自小红书: 这是因为,当时钟隐藏的时候,我们并没有清除定时器。时钟隐藏的时候,定时器的回调函数还在不停地尝试 setState,由于 setState 只能在已经挂载或者正在挂载的组件上调用,所以 React.js 开始疯狂报错。

    多次的隐藏和显示会让 React.js 重新构造和销毁 Clock 组件,每次构造都会重新构建一个定时器。而销毁组件的时候没有清除定时器,所以你看到报错会越来越多。而且因为 JavaScript 的闭包特性,这样会导致严重的内存泄漏

    这时候componentWillUnmount 就可以派上用场了,它的作用就是在组件销毁的时候,做这种清场的工作。例如清除该组件的定时器和其他的数据清理工作。我们给 Clock 添加 componentWillUnmount,在组件销毁的时候清除该组件的定时器:

  • React里面的setState是异步的React里面的setState是异步的React里面的setState是异步的

  • 两个ReatDOM.render要是递交到同一个节点上,最后只会显示一个,递交到不同节点则可以共存。 如果冲突则只显示后面的那一个。 就像是innerHTML的替换一样

  • VirtualDOM的组件首字母一定要大写。 如果不大写,最后编译虽然没有错,但是什么都不会显示。

  • 没有经过特殊处理的话,这些on*的事件监听只能用在普通的HTML文件上,而不能用在组件标签上。(今天快要看完小书第二阶段顺便复习了一遍小书第一阶段发现自己不知不觉又忘掉了这句话)

  • 如果没有没有绑定东西,我们在onClick所调用的那个函数的函数体里面的this,将会是null或者undefined,我们要自行绑定才会有this.因为他这是作为一个函数使用,而不是作为对象传值。

    <h1 onClick={this.FunctionClick.bind(this)} > React </h1>

  • 这样的函数最后将会是先执行两次console,最后才执行this.setState,这就跟我们之前说的callback到promise中的异步和同步异曲同工了。 在这里this.setState被放进缓存之中,等待队列执行。而解决的办法,依旧也和callback,promise有着相近的思想。

handleClickOnLikeButton () {
    console.log(this.state.isLiked)
    this.setState({
      isLiked: !this.state.isLiked
    })
    console.log(this.state.isLiked)
  }

除此之外,这是一个获取用户输入的input.

  handleInputChange(event) {
    this.setState({
      content: event.target.value
    }, () => {
      if (!!this.props.share) {
        const {
          content
        } = this.state;
        this.props.share({
          content
        });
      } else {
        console.log("error");
      }
    });
  }

如果以上不采用回调的形式书写,而是将(if!!this.props.share)里面的东西和this.setState分开写,最后就会造成少了一个输入的现象。

下面是我今天的react笔记。

import React from 'react';
import ReactDOM from 'react-dom';
const title='test_for_jsx';
const pretitle='aaa';
const element=(<div><h1>Hello,{title} and {pretitle}</h1></div>);
ReactDOM.render(element,document.getElementById('root'));

首先是上面这个,若是把pretitle放在element定义的下方,不会报错,react估计会认为它是个空字符或者null.(待查)

React所有的jsx值进行编码,所以可以防止XSS攻击。

看官方的英文文档实在是吃力加犯困啊,还好运气好,找到了React小红书。

这是今天的习题 https://scriptoj.com/problems/7

另外吐槽下刚注册的那个题也好好玩,这个网站和作者超赞!

小红书里面有习题,天知道当我看到那个Accept的感动哈哈哈,刚打完羽毛球,神清气爽解题就是快。

class Computer extends Component{
        constructor(){
                super();
                this.state={
                        status:'off'
                }
        }
        Change(){
                this.setState({
                        status: this.state.status==='off'?'on':'off'
                })
        }
        render(){
                return (<div>
                        <button onClick={this.Change.bind(this)}>开关</button>
                        <Screen showContent={this.state.status==='off'?'显示器关了':'显示器亮了'} />
                        </div>)
        }
}
class Screen extends Component{
        static defaultProps={
                showContent:"无内容"
        }
        render(){
                return (
                        <div className="screen">
                        {this.props.showContent}
                        </div>
                )
        }
}
import React, {
  Component
} from 'react';
import ReactDOM from 'react-dom';
class Input extends Component {
  constructor() {
    super();
    this.state = {
      content: ''
    }
  }
  handleInputChange(event) {
    this.setState({
      content: event.target.value
    }, () => {
      if (!!this.props.share) {
        const {
          content
        } = this.state;
        this.props.share({
          content
        });
      } else {
        console.log("error");
      }
    });
  }
  render() {
    return (
      <div>
        <input type='number' value={this.state.content} onChange={this.handleInputChange.bind(this)} />
      </div>
    )
  }
}
class PercentageShower extends Component {
  static defaultProps = {
    number_value: ''
  }
  render() {
    return (
      <div>{this.props.number_value}%</div>
    )
  }
}
class PercentageApp extends Component {
  constructor() {
    super();
    this.state = {
      content: ''
    }
  }
  handleShare(number) {
    number.content = (number.content * 100).toFixed(2);
    this.setState({
      content: number.content
    })
  }
  render() {
    return (
      <div>
        <Input share={this.handleShare.bind(this)}/>
        <PercentageShower number_value={this.state.content} />
      </div>
    )
  }
}
ReactDOM.render(<PercentageApp />, document.getElementById('root'));