React.js 使用起来相对更加灵活,用户可配置性更高;Vue.js 使用起来相对简洁,因为Vue 开放了许多API,但是因为诸多API在灵活性上被限制。
React开发环境准备
使用 React 的方式
1.通过<script>
标签引入 .js 文件来使用
2.通过 create-react-app 脚手架工具
安装
npx
npx create-react-app my-app
npx 是 npm 5.2+ 及更高版本附带的包运行工具
npm
npm init react-app my-app
npm init <initializer>
在 npm 6+ 中可用
React中的组件
// App.js
import React, { Component } from 'react';
class App extends Component {
render() {
// JSX
return (
<div>
Hello React.
</div>
);
}
}
export default App;
// index.js
import React from 'react'; // 因为使用了 JSX 语法,所以必须引入,不然会编译失败
import ReactDOM from 'react-dom'; // ReactDOM将组件或内容挂载到 DOM 节点上
import './index.css'; // 引入样式文件
import App from './App'; // 引入 APP 组件
// JSX
ReactDOM.render(<App />, document.getElementById('root'));
JSX中的一些语法
import React, { Component, Fragment} from "react";
// 引入 css 样式使用
import './TodoList.css';
class TodoList extends Component {
constructor(props) {
super(props)
this.state = {
inputValue: '',
list: []
}
}
render() {
return (
<Fragment>
<div>
{
// 单行注释必须写成三行这样
}
{/* 多行注释 */}
{/* JSX中的 for 要使用 htmlFor,因为React把与 js 中的 for 语句做区分 */}
<label htmlFor="todoInput"></label>
{/* 给 html 添加 class 时使用 className属性,与 js 的 class 关键字区分 */}
<input
id="todoInput"
className="container"
placeholder="todo"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button className="add-btn" onClick={this.handleClick.bind(this)}>新增</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
// 如果想让标签内容不被转义成字符串
// 如 <h1>to do item </h1> 显示为 标题1 效果而不是字符串
// 可以使用 dangerouslySetInnerHTML
// this.handleItemClick.bind(this, index) 绑定 this 外还向方法传递参数
return (
<li
key={index}
dangerouslySetInnerHTML={{__html: item}}
onClick={this.handleItemClick.bind(this, index)}
>
{/* {item} */}
</li>
)
})
}
</ul>
</Fragment>
);
}
handleInputChange(e) {
// console.log(this)
this.setState({
inputValue: e.target.value
})
}
handleClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ''
})
}
handleItemClick(index) {
// immutable
// React 中, state 不允许我们做任何的改变
const list = [...this.state.list]
list.splice(index, 1)
this.setState({
list: list
})
}
}
export default TodoList;
拆分组件与组件间的传值
TodoList.js
import React, { Component, Fragment } from "react";
import TodoItem from './TodoItem';
import './TodoList.css';
class TodoList extends Component {
constructor(props) {
super(props)
this.state = {
inputValue: '',
list: []
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleClick = this.handleClick.bind(this)
}
render() {
return (
<Fragment>
<div>
<label htmlFor="todoInput">请输入内容: </label>
<input
id="todoInput"
className="container"
placeholder="todo"
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<button className="add-btn" onClick={this.handleClick}>新增</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return (
<TodoItem
key={index}
content={item}
index={index}
deleteItem={this.handleItemClick.bind(this)}
/>
)
})
}
</ul>
</Fragment>
);
}
handleInputChange(e) {
this.setState(() => ({
inputValue: e.target.value
}))
// 相当于
// this.setState(() => {
// return { inputValue: e.target.value }
// })
}
handleClick() {
this.setState(() => ({
list: [...this.state.list, this.state.inputValue],
inputValue: ''
}))
}
handleItemClick(index) {
this.setState(() => {
const list = [...this.state.list]
list.splice(index, 1)
return { list }
})
}
}
export default TodoList;
TodoItem.js
import React, { Component } from 'react';
class TodoItem extends Component {
constructor(props) {
super(props)
this.handleContentClick = this.handleContentClick.bind(this)
}
render() {
const { content } = this.props
return (
<div onClick={this.handleContentClick}>{content}</div>
)
}
handleContentClick() {
const { index, deleteItem } = this.props
deleteItem(index)
}
}
export default TodoItem;
父组件像子组件传值通过属性的方式传值:
<TodoItem
key={index}
content={item}
index={index}
deleteItem={this.handleItemClick.bind(this)}
/>
传递的可以是数据值或方法函数
子组件通过 this.props.属性名
的方式接收使用,<div>{this.props.content}</div>
。由于单向数据流,子组件不能修改父组件传递过来的数据,如需要,应使用父组件传递过来的方法进行操作,父组件在通过属性方式传递方法给子组件时应绑定自身的 this
以便子组件能够访问到父组件的 state
进行数据的修改。
this.setState
应传入一个函数作为参数,函数返回一个对象。
在组件中,方法需要绑定 this
,否则在方法中使用的 this
将会是 underfind
,绑定 this
可在 constructor
时操作。
关于React
声明式开发
像 JQuery 的编程方式是直接操作DOM ,这种编程方式就是命令式,创建页面时告诉DOM如何去挂载创建。
React 是声明式的开发方式,面向数据编程,数据构建好后,React会根据数据去构建页面,节约掉大量DOM操作的代码。
可以与其他框架并存
在使用React的同时还可以使用Angular, Vue,JQuery等其他框架。
组件化
React采用组件化的开发
单向数据流
视图层框架
负责视图的构建,跨组件传值通信则是由Flux、Redux等数据层的框架完成
函数式编程
维护起来较为容易,也便于前端的自动化测试。