Writing in the front

I used to write Vue before, but I started to write React on a whim. React syntax is written according to the syntax sequence of Vue official website document, and a tutorial demo is attached.

The github address for the tutorial is Close2React

React (15.4.1) + React – DOM (15.4.1) + Webpack (1.13.3) + AXIos (0.15.3) + Node (6.2.2). See Environment Configuration below for details.

There are currently two branches of the project, half-ES6 + Master

Half-es6 implements CURD + Axios + Others as master does

The half-ES6 method does not fully use the es6 class concept; the master refines it

Environment configuration

React requires webPack configuration and JSX configuration

First, create a new project, NPM init

Then add the following dependencies to the package

"Dependencies" : {" react ", "^ 15.4.1", "the react - dom" : "^" 15.4.1,}, "devDependencies" : {" axios ":" ^ 0.15.3 ", "Babel - core" : "^ 6.18.2", "Babel - loader" : "^ 6.2.8", "Babel - preset - es2015" : "^ 6.18.0", "Babel - preset - react" : "^ 6.16.0", "Babel - preset - react - hmre" : "^ 1.1.1", "bootstrap" : "^ 4.0.0 - alpha. 2", "CSS - loader" : "^ 0.26.1", "file - loader" : "^ 0.9.0 HTML - webpack -", "plugins" : "^ 2.24.1", "node - sass" : "^ 3.13.0", "open - browser - webpack - plugin" : "0.0.3", "sass - loader" : "^ 4.0.2", "style - loader" : "^ 0.13.1", "url - loader" : "^ 0.5.7", "webpack" : "^ 1.13.3 webpack - dev -", "server" : "^ 1.16.2"}Copy the code

There are two important instructions

  "scripts": {
    "dev": "webpack-dev-server --progress --profile --hot",
    "build": "webpack --progress --profile --colors"
  },Copy the code

webpack.config

In the webpack configuration, I want the directory structure to be horizontal (my own word •༝•, that is, all the things used in the Index page, including sass and JS are written in the index directory, there will be directory diagram at the bottom), the purpose is to achieve, I want to edit the file in SRC, package and generate to the public. The path configuration is written first

var ROOT_PATH = path.resolve(__dirname);
var SRC_PATH = path.resolve(ROOT_PATH, 'src');
var PUBLIC_PATH = path.resolve(ROOT_PATH, 'Public');Copy the code

Coordinates the configuration of the entry file and the output file

entry: {
    index: path.resolve(SRC_PATH, 'index/index.js'),},output: {
    path: PUBLIC_PATH,
    filename: '[name].bundle.js',},Copy the code

The main plugins are the HTML-generated plugin and the auto-browser plugin, as well as the Babel configuration, which keeps their levels up to maximum regardless of what happens

plugins: [
    new HtmlwebpackPlugin({
        title: 'My first react-webpack'
    }),
    new OpenBrowserPlugin({
        url: 'http://localhost:8200'})].babel: { / / configuration Babel
    "presets": ["es2015".'stage-0'.'react'],},Copy the code

NPM run dev will automatically open localhost:8200 and you will see the initialized page in your browser

jsx

When you start to write JS you realize that there are so many warnings,

Don’t worry about googling it.

Download React and React-native here:

Select the corresponding item and save:

There are a lot less warnings, but there are still some warnings. What do we do

Click on the little bulb and select Configure

Check those two boxes, save them, and you’re clean.

Project description

Public is the generated directory and SRC is the write directory

SRC uses a horizontal directory structure (invented word •༝•), meaning that everything used in the index page, including sass and JS, is written in the index directory.

Command run item

npm i

NPM run Build generates the packaged file

npm run dev

Data binding

1. Text Interpolation

<span>{text}</span>

2 HTML interpolation

<div dangerouslySetInnerHTML={{__html: "<p>balabalabalabala....... </p>"}} />

3 Attribute assignment

<span id = {this.props.idName}></span>

<span className = "nav-box"></span>

4 interpolation with JS expression XXX = {ternary expression}

<span className={this.props.idx == this.props.choice? "tab on" : "tab"} ></span>

5 Event Binding

Event binding is the same as property binding

// If class inheritance is not used
getInitialState() {
    return {
        tabTxt: ['CURD'.'Axios'.'Others'].choice: 0,
    }
},

switchChoice(idx){
        this.setState({
            choice: idx
        })
    },

renderTabInit(text, idx) {
    return (<Tab key={idx} idx={idx}
             choose={this.switchChoice}/ / bindingswitchChoicemethodschoice={this.state.choice}/ / datadataThe binding,this.stateI can get the wholestate 
             >{text}</Tab>)},Copy the code

There may be some boom-boom bugs, see the react/React event binding

Binding of CSS and style

1 className

className={this.props.idx == this.props.choice? “tab on” : “tab”}

2 style

The first parenthesis is interpolation, and the second parenthesis represents the style object

style={{color: ‘#FEC264′, fontSize: ’40px’}}


List rendering & Conditional rendering

An array tabTxt is defined in getInitalState

getInitialState() {
        return {
            tabTxt: ['CURD'.'Axios'.'Others'].choice: 0,}},Copy the code

Loop over this subcomponent, each with its own unique key, similar to track-by (or V-bind :key)

renderTabInit(text, idx) {
        return (<Tab key={idx} idx={idx}
                     choose={this.switchChoice}
                     choice={this.state.choice}
        >{text}</Tab>)},Copy the code

List rendering v-for uses map in React

V-if conditional rendering can be ternary, such as complex judgment, need to write logic code before return

render() {
    let currentPage = null;
    if(this.state.choice == 0) {
        currentPage = <PageA />
    } else if (this.state.choice == 1){
        currentPage = <PageB />
    } else {
        currentPage = <PageC />
    }
    return (
        <div id="content">
            <div id="navBox">
                {this.state.tabTxt.map(this.renderTabInit)}
            </div>
            <div id="pageBox">
                {currentPage}
            </div>
        </div>)}Copy the code

The form controls

A form component has several user-influenced properties:

Value for input and Textarea components

Checked, used for input components of type checkbox or radio

Selected, for the Option component

Each form control has an onChange event that listens for component changes:

When the value of the input or textarea changes

When the checked state of the input changes

When the selected state of option changes

Restricted components:

    //es5
    render: function() {
        return <input type="text" value="Hello!" />; } // It doesn't matter if you enter any values in the rendered element, because React is already set to Hello!Copy the code

For user-modified values to be useful, you need to:

  getInitialState() {
    return {value: 'Hello! '};
  },
  handleChange(event) {
    this.setState({value: event.target.value});
  },
  render() {
    let value = this.state.value;
    return <input type="text" value={value} onChange={this.handleChange} />;
  }Copy the code

Unrestricted components:

    //es5
   render: function() {
      return( <div> <input type="radio" name="opt" defaultChecked /> Option 1 <input type="radio" name="opt" /> Option 2 <select defaultValue="C"> <option value="A">Apple</option> <option value="B">Banana</option> <option value="C">Cranberry</option> </select> </div> ); } // User input is immediately reflected on the element. // As with restricted elements, the onChange event is used to listen for changes in values. // Default has an initial value, but this value can be changed by the user and reflected in the interface.Copy the code

Parent-child component communication

Parent-child component communication

// Parent component, equivalent to the largest component
// The child component is a TAB, and three pages, switch TAB to switch page
const Content = React.createClass({
    getInitialState() {
        return {
            tabTxt: ['CURD'.'Axios'.'Others'].choice: 0.// The currently selected TAB subscript
        }
    },

    switchChoice(idx){
        this.setState({ / / modify state
            choice: idx
        })
    },

    renderTabInit(text, idx) {
        return (<Tab key={idx} idx={idx}
                 choice={this.state.choice}  // key\idx\choiceBoth are actspropsThe incomingtabParameter name of the child componentchoose={this.switchChoice}  // chooseAs apropsAs the incomingtabMethod name of child component >{text}</Tab>)
    },

    render() {
        let currentPage = null;
        if(this.state.choice == 0) { // Conditional judgment
            currentPage = <PageA />
        } else if (this.state.choice == 1){
            currentPage = <PageB />
        } else {
            currentPage = <PageC />
        }
        return (
            <div id="content">
                <div id="navBox">{this.state.tabtxt.map (this.renderTabinit)} // loop output</div>
                <div id="pageBox">
                    {currentPage}
                </div>
            </div>)}});Copy the code

When choosing ={this.switchChoice} is used, bind is not used because the class method is not used

Bind: choose={this.switchchoice.bind (this)}

This will not result in a child component pointing to an error if it is not bound to class.

Using the class notation requires manual bind, which is explained at the end of this article

// TAB subcomponent
const Tab = React.createClass({
    chooseTab() {
        this.props.choose(this.props.idx); // Make sure to relay the parent's methods to the child
    },

    render(){
        return (
            <span className={this.props.idx= =this.props.choice? "tab on" : "tab"}
                  style={{color: '#FEC264', fontSize: '40px'}}
                  data-idx={this.props.idx}
                  onClick={this.chooseTab}// Call the child component's method >{this.props.children}</span>)}});Copy the code

Get the DOM element

When your component is not already mounted to the container, you can access it with this.refs

The react-dom method findDOMNode is used to retrieve the dom of the component

In addition:

If ref is set on a native HTML element, it gets a DOM element;

If you set it to a custom component, it gets the component instance, and you need findDOMNode to get the component’s DOM element.

//es5
var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.getDOMNode().focus(); // Get the element from this.refs.xxxxx
  },
  render: function() {
    return<div> <input type="text" ref="myTextInput" /> onClick={this.handleClick} /> </div> ); }});Copy the code

A few common apis

componentDidMount

componentWillReceiveProps(nextProps)


Take a minute and change it to the orthodox class

First, change all createClass to class XXX extends Component

Here’s the code we wrote using half of es6 pose:

// half-es6
import React from 'react';
const List = React.createClass({ // Create a component with createdClass
    getInitialState() { // Initialize data state
        return { // Define state in the function return
            status: false,}},// There must be a comma
    saveLiValue() { // The function to be called within the component
        this.setState({
            status: false})},... })Copy the code

Here’s the code we wrote in full ES6 pose:

// master
// Es6 with class posture
import React, {Component} from 'react';
class List extends Component{
    constructor(props){
        super(props);
        this.state = { 
            status: false,}}// No commas

    saveLiValue() {
        this.setState({
            status: false})}... }Copy the code

Second, in the parent, bind(this) all methods that need to be passed to the child.

This one is a little tricky, but be sure to understand.

Bind (this); bind(this);

2. The purpose of this is to prevent this from pointing to an error when a child component calls a method

For example, the following function initializes a list

// half-es6
// If you bind(this) in this way, the compiled page will be warned
React already provides rich methods to avoid pointing errors, without the need for manual bind
initListLi(val, idx) {
    return( <List {... val} key={idx} index={idx} handleTxtChange={this.handleTxtChange} handleCheckChange={this.handleCheckChange} DeleteItem ={this.deleteitem} />)}, render() {return (<article className="page"> <h3 className="h3">List {this.state.list.length}</h3> <h3 className="h3"> {this.state.didCount}</h3> <ul className="ul"> { this.state.list.map(this.initListLi) } </ul> <Add addLiItem={this.addLiItem}/> </article> ) }Copy the code

But if you use the class notation, you might get a warning saying props is null

At this point, you need to manually bind(this)

// master
// es6 class function event binding,
Bind (this) in the parent if the child needs to call a function
initListLi(val, idx) {
    return( <List {... Val} key = {independence idx} index = {independence idx} / / the following three methods are bound to List the component of this handleTxtChange = {this. HandleTxtChange. Bind (this)} handleCheckChange={this.handleCheckChange.bind(this)} deleteItem={this.deleteItem.bind(this)} /> ) } render() { return ( <article className="page"> <h3 className="h3">List number of items: {this.state.list.length}</h3> <h3 className="h3"> {this.state.didCount}</h3> <ul className="ul"> {this.state.list.map(this.initlistli.bind (this)) // The child component will need to call the function}</ ul> <Add addLiItem={this.addLiItem.bind(this)}/> </article> ) }Copy the code

Write in the back

Github address: Close2React

I’m Gabor Appian, and I’m a cute, algorithmic girl.