f2e-journey / xueqianban

学前班 - 学前端
http://f2e-journey.github.io/xueqianban/
MIT License
320 stars 56 forks source link

我的 React 之旅 #23

Open ufologist opened 8 years ago

ufologist commented 8 years ago

最近上手了 create-react-app 工具, 大大降低了 React 的使用门槛, 扫清了 N 多搭建环境的障碍. 再也不必折腾 N 多工具就可以开启你的 React 之旅了(从此你再也不好意思说 React 好麻烦了)

以前你可能需要准备的环境有:

现在有了 create-react-app, 你只需下面几个命令就够了

npm install -g create-react-app

create-react-app my-app
cd my-app/

npm start
npm run build
  • One Dependency
  • Zero Configuration

Your environment will have everything you need to build a modern React app:

  • React, JSX, and ES6 support.
  • A dev server that lints for common errors.
  • Import CSS and image files directly from JavaScript.
  • Autoprefixed CSS, so you don’t need -webkit or other prefixes.
  • A build script to bundle JS, CSS, and images for production, with sourcemaps.

下面正式开启我的 React 之旅

React Tutorial 学习笔记

React is all about modular, composable components.

For our comment box example, we'll have the following component structure:

- CommentBox
  - CommentList
    - Comment
  - CommentForm

Note that native HTML element names start with a lowercase letter, while custom React class names begin with an uppercase letter.

We pass some methods in a JavaScript object to React.createClass() to create a new React component.

The most important of these methods is called render which returns a tree of React components that will eventually render to HTML.

The <div> tags are not actual DOM nodes; they are instantiations of React div components.

React is safe. We are not generating HTML strings so XSS protection is the default.

You can return a tree of components that you (or someone else) built.

This is what makes React composable: a key tenet of maintainable frontends.

ReactDOM.render() instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.

The ReactDOM module exposes DOM-specific methods, while React has the core tools shared by React on different platforms (e.g., React Native).

It is important that ReactDOM.render remain at the bottom of the script for this tutorial. ReactDOM.render should only be called after the composite components have been defined.

var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        Hello, world! I am a CommentBox.
      </div>
    );
  }
});
ReactDOM.render(
  <CommentBox />,
  document.getElementById('content')
);

Data passed in from a parent component is available as a 'property' on the child component. These 'properties' are accessed through this.props.

We access named attributes passed to the component as keys on this.props and any nested elements as this.props.children.

<Comment author="Pete Hunt" num={1}>This is one comment</Comment>

this.props.author   => Pete Hunt           // string
this.props.num      => 1                   // number
this.props.children => This is one comment // any nested elements

That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it:

<span dangerouslySetInnerHTML={ {__html: '<input type="text"/>'} } />

props are immutable: they are passed from the parent and are "owned" by the parent.

To implement interactions, we introduce mutable state to the component.

this.state is private to the component and can be changed by calling this.setState(). When the state updates, the component re-renders itself.

render() methods are written declaratively as functions of this.props and this.state. The framework guarantees the UI is always consistent with the inputs.

getInitialState() executes exactly once during the lifecycle of the component and sets up the initial state of the component.

componentDidMount() is a method called automatically by React after a component is rendered for the first time.

Controlled components

A Controlled component does not maintain its own internal state; the component renders purely based on props.

// User input will have no effect on the rendered element because React has declared the value to be Hello!.
render: function() {
    return <input type="text" value="Hello!" />;
}

// To update the value in response to user input, you could use the onChange event:
render: function() {
    return <input type="text" value={this.state.value} onChange={this.handleChange} />;
}

React attaches event handlers to components using a camelCase naming convention.

React.createClass() automatically binds each method to its component instance, obviating the need for explicit binding.

Autobinding and Event Delegation

最后奉上代码大家可以尝尝鲜

// es2015
import React, {
    Component
} from 'react';

class CommentBox extends Component {
    constructor(props) {
        super(props);

        this.state = {
            comments: props.comments,
            text: 'init'
        };
    }
    componentDidMount() {
        console.log('a component is rendered for the first time');
    }
    render() {
        return (
            <div>
                <ul>{this.state.comments.map(function(comment) {
                    return <li key={comment.id}>{comment.text}</li>
                })}</ul>
                <input ref="commentInput" onChange={this.handleChange.bind(this)} type="text" value={this.state.text} />
                <br/>
                <span dangerouslySetInnerHTML={ {__html: this.state.text} }></span>
            </div>
        );
    }

    handleChange(event) {
        // 设置组件状态, 会自动刷新 UI, 即自动调用 render 方法
        this.setState({
            comments: this.state.comments.concat({
                id: Date.now(),
                text: event.target.value       // 可以通过 event 来获取元素
            }),
            text: this.refs.commentInput.value // 也可以通过 refs 来获取元素
        });
    }
}
CommentBox.propTypes = {
    comments: React.PropTypes.array.isRequired
};

export default CommentBox;

// use component
<CommentBox comments={ [{id: 1, text: 'comment1'}] } />
zhangolve commented 8 years ago

为什么我npm run build 之后生成的build文件夹里的index.html 文件在浏览器内打开是空白的呢

ufologist commented 8 years ago

@zhangolve 请再详细描述下你的情况, 否则我没有办法提供更多的建议.

针对你说的如下问题:

index.html 文件在浏览器内打开是空白的

这种情况下你最好通过 chrome devtools 查看下 index.html 是否正确引用了 npm run build 打包后的文件, 而且都是存在且正常的.

zhangolve commented 8 years ago

@ufologist 几个月以前的疑惑了,现在已经解决了,当时不是太懂打包之后的文件怎么用。其实是还需要对生成的文件进行引用的。当时并不懂,所以就提了问题。