标签:conf 文件 可变 标签 div 运算符 方便 对比 path
1.首先,这两个框架,都是以组件化的思想进行开发的!
2.从开发团队上进行比较:
3.从社区方面进行对比:
4.从移动App开发方面:
推荐使用yarn来安装node包,时间更快
mkdir react-demo cd react-demo npm init -y
yarn add react react-dom webpack webpack-cli webpack-dev-server babel babel-cli babel-core babel-loader@7 babel-preset-react babel-preset-env babel-preset-es2015
目录下新建webpack配置文件webpack.config.js
module.exports = { entry: "./main.js", output: { path: "/", filename: "index.js" }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules)/, use: { loader: "babel-loader", options: { presets: [‘env‘, ‘react‘, ‘es2015‘] } } } ] } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="root"></div> <script src="./index.js"></script> </body> </html>
目录下新建main.js
import React, { Component } from ‘react‘; import ReactDom from ‘react-dom‘; class App extends Component { render() { return <h1> Hello, world! </h1> } } ReactDom.render( <App />, document.getElementById(‘root‘) )
"scripts": { "start": "webpack-dev-server --inline --hot --open --port 8090 --mode development" },
yarn start
create-react-app是react脚手架的名称
npm5.2或者更高带来的一个新特性,可以不同全局安装脚手架,就可以直接使用脚手架
npx create-react-app my-app cd my-app yarn start
3.2.运行成功
│ .gitignore git忽略清单
│ package.json 项目配置文件
│ README.md 说明文件
│
├─public 公共资源
│ favicon.ico 图标
│ index.html 首页html
│ manifest.json 缓存清单
│
└─src 源代码
App.css 组件的样式文件
App.js 组件文件
App.test.js 组件的测试文件
index.css 全局样式文件
index.js 入口文件
logo.svg logo图标
serviceWorker.js serviceWorker文件
jsx是React框架中的一种语法,它是JavaScript的语法拓展。既可以在js文件中写js逻辑代码,也可以在js文件中写HTML语言。
JSX是JavaScript XML的简写
import React from ‘react‘; import ReactDOM from ‘react-dom‘; // const App = () => <h1>我就是jsx</h1>; const App = function () { return ( <h1>我就是jsx</h1> ); } ReactDOM.render(<App />, document.getElementById(‘root‘));
组件中,必须返回一个根元素
如下列语法是错误的!
const App = function () { return ( <h1>我就是jsx</h1> <h1>我就是jsx</h1> ); }
假设想要在根目录下直接渲染2个标签,可以使用Fragment标签,类似vue中的template
引入Fragment组件
import React, { Fragment } from ‘react‘;
包裹标签
import React, { Fragment } from ‘react‘; import ReactDOM from ‘react-dom‘; const App = ()=> { return ( <Fragment> <h1>我就是jsx</h1> <h1>我就是jsx</h1> </Fragment> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
1.普通渲染
<h1>我就是jsx</h1>
2.数学表达式
<h1>{1 + 1}</h1>
3.字符串
<h1>{‘hello world‘}</h1>
4.bool类型-无法渲染
<h1>{isBoy}</h1>
5.使用变量
<h1>{msg}</h1>
6.三目运算符
<h1>{isBoy ? "男生" : "女生"}</h1>
7.调用方法
const format = (msg) => { return ‘---‘ + msg + ‘---‘; } <h1>{format(msg)}</h1>
8.使用对象
const person = { name: "沙和尚" }; <h1>{person.name}</h1>
完整代码
import React, { Fragment } from ‘react‘; import ReactDOM from ‘react-dom‘; const msg = "你们好呀"; const isBoy = false; const format = (msg) => { return ‘---‘ + msg + ‘---‘; } const person = { name: "沙和尚" }; const App = () => { return ( <Fragment> <h1>我就是jsx</h1> {/* 数字 */} <h1>{1 + 1}</h1> {/* 字符串 */} <h1>{‘hello world‘}</h1> {/* bool类型 */} <h1>{isBoy}</h1> {/* 使用变量 */} <h1>{msg}</h1> {/* 3目运算符 */} <h1>{isBoy ? "男生" : "女生"}</h1> {/* 调用方法 */} <h1>{format(msg)}</h1> {/* 使用对象 */} <h1>{person.name}</h1> </Fragment> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
按照这个思路去理解即可
如下所示:
import React from ‘react‘; import ReactDOM from ‘react-dom‘; const msg = "今天天气不错"; const App = () => { return ( <div > { <div> <h1>我也是大头 {msg} </h1> <h1>我也是大头 {msg} </h1> </div> } </div> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
加强版本,必须要掌握
import React from ‘react‘; import ReactDOM from ‘react-dom‘; const list = [‘苹果‘, ‘香蕉‘, ‘雪梨‘, ‘西瓜‘]; const App = () => { return ( <div > { <div> { list.map(function (v) { return ( <h1 key={v}>{v}</h1> ) }) } </div> } </div> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
终极版 最常用
import React from ‘react‘; import ReactDOM from ‘react-dom‘; const list = [‘苹果‘, ‘香蕉‘, ‘雪梨‘, ‘西瓜‘]; const App = () => { return ( <div > { <div> { list.map(v => <h1 key={v}>{v}</h1>) } </div> } </div> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
{ // 这里是单行注释 } { /* 这里是多行注释 这里是多行注释 这里是多行注释 这里是多行注释 */ }
jsx标签上可以设置绝大部分和以前html标签一样的属性,如checked、图片的src
除此之外
1.html的class属性改为className
<div className="redCls">大头大头</div>
2.html中label标签的for属性改为htmlFor
<label htmlFor="inp">
点我点我
<input id="inp" type="text" />
</label>
3.标签中的自定义属性使用data
<div data-index={‘hello‘} >自定义属性</div>
4.渲染html字符串使用dangerouslySetInnerHTML属性
<li dangerouslySetInnerHTML={{__html:"<i>打我呀</i>"}}></li>
5.bool类型的值可以这样用
<input type="checkbox" checked={true} />
6.当属性太多了,可以使用...拓展运算符
const props={ className:"redCls", "data-index":5 } <div {...props}>展开属性</div>
JSX可以像传统的HTML标签一样添加行内样式,不同的是,要通过对象的方式来实现。并且属性名是以驼峰命名。
import React from ‘react‘; import ReactDOM from ‘react-dom‘; import "./index.css"; const App = () => { return ( <div style={{ color: ‘yellow‘, fontSize: "50px", "backgroundColor": ‘blue‘ }} > 颜色好好看呀 </div> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
4.7.JSX创建组件的本质(了解即可)
JSX俗称 语法糖,提供了一种更好使用的语法让我们使用,其本质是调用React.createElement实现的
React.createElement,接收3个参数
import React from ‘react‘; import ReactDOM from ‘react-dom‘; import "./index.css"; const parentProps = { className: "redCls", "data-index": 100 } const App = () => { return React.createElement( "div", parentProps, [ React.createElement( "span", null, "你们好呀" ), React.createElement( "span", null, "你们好呀" ) ] ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
在React中,组件分为两种,类组件和函数式组件
import React,{Component} from ‘react‘; import ReactDOM from ‘react-dom‘; import "./index.css"; class App extends Component { render() { return ( <div> hello </div> ) } } ReactDOM.render(<App />, document.getElementById(‘root‘))
也叫做无状态组件
简单功能组件可以使用函数式组件,性能更高。
函数式组件其实就是一个函数,只不过函数内部要返回对应的标签
import React from ‘react‘; import ReactDOM from ‘react-dom‘; import "./index.css"; // 这个就是函数式组件 const App = () => { return ( <div>这个就是一个简单的函数式组件</div> ) } ReactDOM.render(<App />, document.getElementById(‘root‘))
在React中,状态和属性都可以实现数据动态化,我们现在开始这两个知识
在react中,内部组件的数据是通过state来实现和管理
我们之前使用变量,都是脱离了组件本身,正确来说,组件自身是应该具有私有和独立的数据(状态)的,这个私有的数据和状态就叫做state,以后,只要说到数据的状态那么就是指state
在类组件中,state的声明分为两种方式
1.类属性的方式声明
class Person extends Component { // 1 声明 state state = { date: "2008", msg: "大头大头下雨不愁" } render() { return ( <div> {/* 2 使用state */} <h1>{this.state.date}</h1> <h2>{this.state.msg}</h2> </div> ) } }
2.构造函数中声明
class Person extends Component { // 1 构造函数中 声明 state constructor() { // 1.1 必须在this之前调用super()方法 super(); this.state = { date: "2008", msg: "大头大头下雨不愁" } } render() { return ( <div> {/* 2 使用state */} <h1>{this.state.date}</h1> <h2>{this.state.msg}</h2> </div> ) } }
state的赋值方式通过this.setState方式来实现
需要注意的是,不能使用this.state.date=100 直接修改
class Person extends Component { state = { date: 2008 } // 2 事件的声明 要使用箭头函数 handleClick = () => { // 3 获取state中的日期 let { date } = this.state; // 4 修改state中的日期 this.setState({ date: date + 1 }); } render() { return ( // 1 绑定事件 事件名必须驼峰命名 <div onClick={this.handleClick}> <h1>{this.state.date}</h1> </div> ) } }
react为了优化性能,将state的赋值代码改成异步的方式,为了避免反复的设置state而引发的性能损耗问题。
看看下面打印的值
class Person extends Component { state = { date: 2008 } handleClick = () => { let { date } = this.state; // 1 修改state中的日期 增加 1000 this.setState({ date: date + 1000 }); // 2 看看这个date是多少 console.log(this.state.date); } render() { return ( <div onClick={this.handleClick}> <h1>{this.state.date}</h1> </div> ) } }
有时候,我们希望在一设置值的时候,就希望马上得到最新的state的值,那么可以将代码改为下列的写法,给setState添加一个回调函数,回调中可以获取到修改后的state的值
class Person extends Component { state = { date: 2008 } handleClick = () => { let { date } = this.state; // 添加一个回调函数 this.setState({ date: date + 1000 }, () => { // date的值为 3008 console.log(this.state.date); }); } render() { return ( <div onClick={this.handleClick}> <h1>{this.state.date}</h1> </div> ) } }
有时候,setState还可以接收一个函数,函数内可以实时获取state中的值,不存在延迟。
this.setState(preState => { console.log("上一次的state", preState.date); return { date: preState.date + 1000 } }) this.setState(preState => { console.log("上一次的state", preState.date); return { date: preState.date + 1 } })
props意思是属性,一般存在父子组件中,用于父向子传递数据。
子组件不能修改接受到的props值
1.声明一个类组件HomeTop父组件的数据通过this.props来获取
class HomeTop extends Component { render() { return ( <h1>屋顶的颜色是 {this.props.acolor} 尺寸 {this.props.asize}</h1> ) } }
2.声明一个函数式组件HomeFotter,父组件传递的数据 需要在函数的形参props上接收
const HomeFooter = (props) => { return <h1>屋底的颜色是 {props.bcolor} 尺寸 {props.bsize}</h1> }
3.声明父组件,并在标签上通过属性的方式进行传递数据
class Home extends Component { state = { color: "blue", size: 100 } render() { return ( <div> <HomeTop acolor={this.state.color} asize={this.state.size} ></HomeTop> <HomeFooter bcolor={this.state.color} bsize={this.state.size} ></HomeFooter> </div> ) } }
4.需要注意的是父组件中的变量名是color,size而HomeTop和HomeFotter中修改了一下变量名,分别是acolor,asize和bcolor,bsize。
完整代码
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; class HomeTop extends Component { render() { return ( <h1>屋顶的颜色是 {this.props.acolor} 尺寸 {this.props.asize}</h1> ) } } const HomeFooter = (props) => { return <h1>屋底的颜色是 {props.bcolor} 尺寸 {props.bsize}</h1> } class Home extends Component { state = { color: "blue", size: 100 } render() { return ( <div> <HomeTop acolor={this.state.color} asize={this.state.size} ></HomeTop> <HomeFooter bcolor={this.state.color} bsize={this.state.size} ></HomeFooter> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
当想要在类组件的构造函数中,获取到props时,需要如下使用:
constructor(props) {
super(props);
console.log(props);
}
当父元素没有传递props属性时,子组件可以指定一个默认props属性值来使用。
通过 组件名.defaultProps 来指定
import React from ‘react‘; import ReactDOM from ‘react-dom‘; let HomeNav = (props) => { return <h1> 导航为 {props.color} </h1> } // 指定一个默认属性 HomeNav.defaultProps = { color: "yellow" } class Home extends Component { state = { color: "blue" } render() { return ( <div> <HomeNav></HomeNav> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
在一些要求代码更为严格的项目中,父组件传递数据的格式,必须和子组件要求的格式保持一致,否则就认为代码出错。
如子组件要求的是数字类型(100),而父组件传递的是字符串类型(“100”)。
这个需求可以通过react中的props类型检验来完成。
自React v15.5起,react.PropTypes已移入另一个包中。请使用prop-types库代替
yarn add prop-types --dev
引入
import PropTypes from ‘prop-types‘;
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; // 1 引入 prop-types import PropTypes from ‘prop-types‘; let HomeNav = (props) => { return <h1> 导航为 {props.color} 数量为 {props.nums} </h1> } // 2 指定要求接收的数据格式 HomeNav.propTypes ={ color:PropTypes.string, nums:PropTypes.number } class Home extends Component { state = { color: "blue", nums:100 } render() { return ( <div> <HomeNav {...this.state}></HomeNav> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
props.children可以实现类似Vue中的插槽功能(slot)
let HomeNav = (props) => { return ( <div> <div>标题</div> <div>{props.children}</div> </div> ) }
class Home extends Component { render() { return ( <div> <HomeNav {...this.state}> {/* 这里放动态插入的内容 */} <div>小标题你</div> </HomeNav> </div> ) } }
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; import PropTypes from ‘prop-types‘; let HomeNav = (props) => { return ( <div> <div>标题</div> <div>{props.children}</div> </div> ) } class Home extends Component { render() { return ( <div> <HomeNav {...this.state}> {/* 这里放动态插入的内容 */} <div>小标题</div> </HomeNav> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
相同
不同
总结:尽量少用state,尽量多用props,这样既能提高组件的可复用性,又能降低维护成本。
React元素的事件处理和DOM元素的很相似,但是有一点语法上的不同:
<button onclick="activateLasers()">
Activate Lasers
</button>
<button onClick={this.handleClick}> Activate Lasers </button>
观察以下的this值 它是undefined
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; class Home extends Component { state = { msg: "大家好呀" } handleClick() { // undefined console.log(this); } render() { return ( <div> <div onClick={this.handleClick} >小标题</div> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
因为在react中,绑定事件不是原生HTML的dom元素,onClick只是react帮我们做的一个中间的映射,那么他在处理事件的时候,是不会处理this的指向的,我们需要手动处理这个this
1.绑定事件的时候使用bind来锁定this 代码丑陋,不推荐
<div onClick={this.handleClick.bind(this)} >小标题</div>
2.在构造函数中使用bind修改this执行(推荐)
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; class Home extends Component { state = { msg: "大家好呀" } constructor() { super(); // 重新绑定this this.handleClick = this.handleClick.bind(this); } handleClick() { console.log(this); } render() { return ( <div> <div onClick={this.handleClick} >小标题</div> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
3.将事件的执行,改成箭头函数的方式(推荐)
import React, { Component } from ‘react‘; import ReactDOM from ‘react-dom‘; class Home extends Component { state = { msg: "大家好呀" } // 修改为箭头函数的方式 handleClick = () => { console.log(this); } render() { return ( <div> <div onClick={this.handleClick} >小标题</div> </div> ) } } ReactDOM.render(<Home />, document.getElementById(‘root‘))
执行类似以前HTML的DOM事件传参一样的功能
<button onclick="show(‘大家好‘)"></button>
React中的写法为:
不推荐,容易导致意外情况(BUG)
<button onClick={() => { this.handleClick(‘red‘) }}>红色</button>
推荐写法:
<button onClick={ this.handleClick.bind(this,‘red‘) }>红色</button>
标签:conf 文件 可变 标签 div 运算符 方便 对比 path
原文地址:https://www.cnblogs.com/sauronblog/p/12670830.html