react是facebook开源的,为什么高效的原因,是因为使用了虚拟dom技术,可以很大程度的复用。
1.基本语法
helloWorld,babel的引入是为了将jsx转换为js,使用jsx可以更快的创建虚拟dom。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello_react</title>
</head>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
const VDOM = <h1>hello,React</h1>
ReactDOM.render(VDOM,document.getElementById('test')) /*此处不写引号,不是字符串*/
</script>
</body>
</html>
JSX的基本语法:
- 定义虚拟DOM时,不要写引号
- 标签中混入JS表达式要用{},注意用const xxx=可以接收的才叫表达式
- 样式的类名指定不要用class,要用className
- 内联样式,要用style={{key:value}}形式
- 只有一个根标签
- 标签必须闭合
- 标签首字母:
(1)若小写字母开头,则把标签转化为html同名元素,若没有对应同名元素则报错
(2)若大写字母开头,react就去渲染对应的组件,若组件没有定义则报错。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
const title = 'title'
const VDOM = (
<div>
<h1 className={title} style={{ color: 'red' }}>
<span>hello,React</span>
</h1>
<Good></Good>
</div>
)
ReactDOM.render(VDOM, document.getElementById('test')) /*此处不写引号,不是字符串*/
</script>
</body>
</html>
2.面向组件编程
js的模块化只是拆分html,而组件编程则是html、css、js、img、video等整合起来是一个组件,优点是复用编码,提高效率。
2.1函数式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
function Demo() {
return <h1>我是一个函数式组件(适用于简单的自定义)</h1>;
}
ReactDOM.render(<Demo />, document.getElementById("test"));
</script>
</body>
</html>
2.2类式组件
2.2.1类的初识
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 创建一个Person类
class Perseon {
// 构造器方法
constructor(name, age) {
this.name = name;
this.age = age;
}
// 一般方法
speak() {
// speak方法在类的原型对象上,供实例使用
// 通过Person实例调用speak时,speak中的this就是Person实例
console.log(`我叫${this.name},我已经${this.age}了`);
}
}
class Student extends Perseon {
constructor(name, age, grade) {
// 子类使用构造器一定要使用super且必须在前面
super(name, age);
this.grade = grade;
}
// 重写父类继承的方法
speak(name,age,grade){
console.log(`我叫${this.name},我已经${this.age}了,在读${this.grade}`);
}
}
const mm = new Perseon("小满", 10);
console.log(mm);
mm.speak();
// call可以更改函数里的this指向
mm.speak.call({ name: "didi", age: 8 });
const ls = new Student("李四", "18", "大一");
ls.speak();
</script>
</body>
</html>
2.2.2使用
React解析组件标签时,发现组件是使用类定义的,会new出该类实例,并通过该实例调用到原型上的render
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class MyComponent extends React.Component{
render(){
return '我是一个类式组件'
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>
</body>
</html>
3.State状态
借助构造器初始化状态并使用,通过点击事件修改状态。
标准写法(强制绑定)
下面是标准写法,借助构造器的this对state进行初始化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component {
constructor(props) {
super(props);
// 初始化状态
this.state = { isHot: true, wind: "微风" };
// 解决changeWeather中指向问题
this.changeWeather = this.changeWeather.bind(this);
}
render() {
const { isHot, wind } = this.state;
return (
<h1 onClick={this.changeWeather}>
今天天气{isHot ? "炎热" : "凉爽"},{wind}
</h1>
);
}
changeWeather() {
const isHot = this.state.isHot;
this.setState({ isHot: !isHot });
console.log("修改天气:", this.state.isHot);
}
}
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
</body>
</html>
简化写法(箭头函数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<style>
.title {
font-size: large;
color: blue;
}
</style>
<body>
<div id="test"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component {
// 自定义状态
state = { isHot: true, wind: "微风" };
render() {
const { isHot, wind } = this.state;
return (
<h1 onClick={this.changeWeather}>
今天天气{isHot ? "炎热" : "凉爽"},{wind}
</h1>
);
}
// 自定义方法——用赋值语句+箭头函数的形式
changeWeather = () => {
console.log(this);
const isHot = this.state.isHot;
this.setState({ isHot: !isHot });
console.log("修改天气:", this.state.isHot);
};
}
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
</body>
</html>
4.props多种属性
三点运算符…表示展开,是对于一个数组。
基本使用
{...Person}在原生es6语法中,表示克隆一个对象
{...Person,name:'jack'}表示克隆一个对象并替换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>hello_react</title>
</head>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 先引入核心库、扩展库、babel库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<script
type="text/javascript"
src="../js/react-dom.development.js"
></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component {
render() {
const { area, day, weather } = this.props;
return (
<ul>
<li>{area}</li>
<li>{day}</li>
<li>{weather}</li>
</ul>
);
}
}
const p = { area: "福州", day: "11月25日", weather: "晴" };
//这里不是表示克隆而是展开p,因为react+babel,原生会报错,而且只有标签属性可以
ReactDOM.render(<Weather {...p} />, document.getElementById("test1"));
ReactDOM.render(
<Weather area="泉州" day="11月25日" weather="阴" />,
document.getElementById("test2")
);
ReactDOM.render(
<Weather area="厦门" day="11月25日" weather="大风" />,
document.getElementById("test3")
);
</script>
</body>
</html>
标签属性限制
Person.propTypes = {
name: PropTypes.string.isRequired,//限制name必传,且为字符串
sex: PropTypes.string,//限制sex为字符串
age: PropTypes.number,//限制age为数值
speak:PropTypes.func//限制speak为函数
};
Person.defaultProps = {
sex: "保密",//sex默认值保密
};
简写
class Person extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
sex: PropTypes.string, //限制sex为字符串
age: PropTypes.number, //限制age为数值
speak: PropTypes.func, //限制speak为函数
};
static defaultProps = {
sex: "保密", //sex默认值保密
};
render() {
const { name, sex, age } = this.props;
return (
<ul>
<li>{name}</li>
<li>{sex}</li>
<li>{age + 1}</li>
</ul>
);
}
}
5.refs
正文
字符串形式
class Demo extends React.Component {
showData = () => {
console.log(this);
const {input1} = this.refs
console.log(input1.value);
};
render() {
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>获取数据</button>
<input id="input2" placeholder="失去焦点提示数据" />
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test1"));
回调函数形式
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
const { input1 } = this.refs;
console.log(this.input1.value);
};
render() {
return (
<div>
<input
ref={(c) => (this.input1 = c)}
type="text"
placeholder="点击按钮提示数据"
/>
<button onClick={this.showData}>获取数据</button>
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test1"));
</script>
回调函数形式
myRef1 = React.createRef();
<input
ref={this.myRef1}
type="text"
placeholder="点击按钮提示数据"
/>
<script type="text/babel">
class Demo extends React.Component {
state = { isHot: true };
myRef1 = React.createRef();
myRef2 = React.createRef();
showData = () => {
console.log(this.myRef1.current.value);
};
showData2 = () => {
alert(this.myRef2.current.value);
};
changeWeather = () => {
const { isHot } = this.state;
this.setState({ isHot: !isHot });
};
render() {
const { isHot } = this.state;
return (
<div>
<h1>今天天气很{isHot ? "炎热" : "凉爽"}</h1>
<input
ref={this.myRef1}
type="text"
placeholder="点击按钮提示数据"
/>
<button onClick={this.showData}>获取数据</button>
<button onClick={this.changeWeather}>点击切换天气</button>
<input
onBlur={this.showData2}
ref={this.myRef2}
type="text"
placeholder="失去焦点提示数据"
/>
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test1"));
</script>