0913 NOTE
React是什么?
一个将数据渲染为HTML视图的js库
React的特点:
1.采用组件化模式,声明式编码,提高开发效率及组件复用率
2.React Native中可以使用React语法进行移动端开发
3.虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互
React实现:
数据=>虚拟DOM=>真实DOM
虚拟DOM的两种创建方式
1.js创建
React.createElement('h1',{id:"title"},React.createElement('span',{},"Hello React"))
ReactDOM.render(VDOM,document.getElementById('test'))
2.jsx创建
<script type="text/babel">/*必须加babel,用于将jsx翻译成js*/
let VDOM = <h1 id="title"><span>Hello,React</span></h1>; //不加引号,不是字符串
ReactDOM.render(VDOM,document.getElementById('test'));
</script>
jsx出现的原因:解决虚拟DOm创建的繁琐问题,实际是原生js的语法糖
虚拟DOM与真实DOM
虚拟DOM:
1.本质是一般对象
2.虚拟DOM用于React内部,没有真实DOM那么多的属性
3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上
jsx语法规则
jsx:javascript XML js扩展语法
语法规则:
1.定义虚拟DOM时,不写引号
2.标签中想借用js表达式调用变量时,用{}包含变量名
3.jsx中,样式类名指定用className而不是class
4.jsx中,内联样式需用双括号包裹对象而非字符串
5.虚拟DOM只允许有一个根标签
6.标签必须闭合
7.标签首字母:
a.小写字母开头,则将该标签转为html中同名元素,若无对应html元素,报错
b.大写字母开头,则react会去渲染对应组件,组件未定义则报错
组件与模块
模块:复用js,简化js编写,提高js运行效率
组件:服用代码,简化项目代码,提高运行效率
组件定义方式
函数式组件:
<script type="text/babel">
function Demo(){
return <h2>reacttest</h2>
}
ReactDOM.render(<Demo/>,document.qetElementById("test"))
</script>
步骤:
创建函数式组件:
React解析组件标签→找到对应组件→发现组件由函数定义,调用该函数,将返回的虚拟DOM转为真实DOM,渲染呈现在页面中
function Demo(){
return <h2>reacttest</h2>
}
ReactDOM.render(<Demo/>,document.qetElementById("test"))
//注意:组件,开头字母大写,否则会按照html标签解析,报错
//标签需要闭合
注:babel编译后js环境进入严格模式
类式组件:
类式组件创建必须继承react中的内置类React.Component
//创建类式组件
class MyTest extends React.Component{
render(){
return <h1><span>Hello,React</span></h1>
}
}
/*
执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
*/
复杂组件的定义:
与简单组件的区别→复杂组件有状态state
状态state是组件实例上的属性
初始化state:
class MyTest extends React.Component{
constructor(props){
super(props)
}
render(){
return <h1><span>Hello,React</span></h1>
}
}
react中的事件绑定的注意事项:
1.小驼峰命名,如onClick,不符合命名规则报错
2.行内属性实现事件监听时,通过花括号将事件函数传入,与原生js给入字符串,解析成函数不同,对比:οnclick=“clickHandler”||onClick={clickHandler}
3.类中方法默认开启了局部的严格模式,需要注意this指向问题
setState的使用
注意:状态不可直接更改,需要借助内置API:setState更改
//1.创建组件
class Weather extends React.Component{
//构造器调用几次? ———— 1次
constructor(props){
console.log('constructor');
super(props)
//初始化状态
this.state = {isHot:false,wind:'微风'}
//解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this)
}
//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
render(){
console.log('render');
//读取状态
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
//changeWeather调用几次? ———— 点几次调几次
changeWeather(){
//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
console.log('changeWeather');
//获取原来的isHot值
const isHot = this.state.isHot
//注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
this.setState({isHot:!isHot})
console.log(this);
//注意:状态(state)不可直接更改,下面这行就是直接更改!!!
//this.state.isHot = !isHot //这是错误的写法
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'))
state简写:
class MyTest extends React.Component {
state = {isTrue:false};
render() {
let {isTrue} = this.state;
return <h1><span onClick={this.changetalk}>你说的{isTrue ? "对" : "不对"}!</span></h1>
};
changetalk = ()=>{
// console.log(this.state.isTrue);
let isTrue = this.state.isTrue;
this.setState({isTrue : !isTrue})
}
}
ReactDOM.render(<MyTest />, document.getElementById("test"))
props属性
基本使用:
class Person extends React.Component {
render() {
let { pname, page, pgender } = this.props;
return (
<ul>
<li>姓名:{pname}</li>
<li>性别:{pgender}</li>
<li>年龄:{page}</li>
</ul>
)
}
}
ReactDOM.render(<Person pname="凯哥" pgender="男" page="18" />,document.getElementById("test1"))
ReactDOM.render(<Person pname="小胖砸" pgender="男" page="666" />,document.getElementById("test2"));
ReactDOM.render(<Person pname="小菜鸟" pgender="男" page="888" />,document.getElementById("test3"));
批量传递:
注意:
1.展开运算符…在react的babel标签中可以展开对象,但是仅适用于标签属性
2.props只读
//props批量传递
class Person extends React.Component {
render() {
let { pname, page, pgender } = this.props;
return (
<ul>
<li>姓名:{pname}</li>
<li>性别:{pgender}</li>
<li>年龄:{page+1}</li>
</ul>
)
}
}
//默认属性设置
Person.defaultProps = {
pgender:"小样,居然想性别保密?",
page:999,
}
//属性值规范
Person.propTypes = {
pname:PropTypes.string.isRequired,
pgender:PropTypes.string,
page:PropTypes.number,
}
let kaige = {pname:"凯哥",pgender:"男",page:18};
let xiaopang = {pname:"小胖砸",pgender:"男",page:666};
let cainiao = {pname:"小菜鸟",pgender:"男",page:"888"};
//展开运算符实现批量传递
ReactDOM.render(<Person {...kaige} />, document.getElementById("test1"));
ReactDOM.render(<Person {...xiaopang} />, document.getElementById("test2"));
ReactDOM.render(<Person pname="小菜鸟" />, document.getElementById("test3"));
props简写:
//其实就是将静态属性封装进类,es5→es6
//简写
class Person extends React.Component {
render() {
let { pname, page, pgender } = this.props;
return (
<ul>
<li>姓名:{pname}</li>
<li>性别:{pgender}</li>
<li>年龄:{page + 1}</li>
</ul>
)
}
//默认属性设置
static defaultProps = {
pgender: "小样,居然想性别保密?",
page: 999,
}
//属性值规范
static propTypes = {
pname: PropTypes.string.isRequired,
pgender: PropTypes.string,
page: PropTypes.number,
}
}
let kaige = { pname: "凯哥", pgender: "男", page: 18 };
let xiaopang = { pname: "小胖砸", pgender: "男", page: 666 };
let cainiao = { pname: "小菜鸟", pgender: "男", page: "888" };
//展开运算符实现批量传递
ReactDOM.render(<Person {...kaige} />, document.getElementById("test1"));
ReactDOM.render(<Person {...xiaopang} />, document.getElementById("test2"));
ReactDOM.render(<Person pname="小菜鸟" />, document.getElementById("test3"));
类式组件中的构造函数与props
通常,在 React 中,构造函数仅用于以下两种情况:
1.通过给 this.state
赋值对象来初始化内部 state。
2.为事件处理函数绑定实例
在为 React.Component 子类实现构造函数时,应在其他语句之前前调用 super(props)
。否则,this.props
在构造函数中可能会出现未定义的 bug。
函数式组件使用props
function Person(props) {
let { pname, page, pgender } = props;
return (
<ul>
<li>姓名:{pname}</li>
<li>性别:{pgender}</li>
<li>年龄:{page + 1}</li>
</ul>
)
}
Person.defaultProps = {
pgender: "小样,居然想性别保密?",
page: 999,
}
Person.propTypes = {
pname: PropTypes.string.isRequired,
pgender: PropTypes.string,
page: PropTypes.number,
}
let kaige = { pname: "凯哥", pgender: "男", page: 18 };
let xiaopang = { pname: "小胖砸", pgender: "男", page: 666 };
let cainiao = { pname: "小菜鸟", pgender: "男", page: 888 };
ReactDOM.render(<Person {...kaige} />, document.getElementById("test1"));
ReactDOM.render(<Person {...xiaopang} />, document.getElementById("test2"));
ReactDOM.render(<Person {...cainiao} />, document.getElementById("test3"));
注意:函数式组件调用props属性没问题,但是无法调用state与refs,除非通过hooks