JSX语法
1、标签不能添加引号,换行用括号包裹,并且只有一个根标签
const H1 = <h1>标题</h1>
const Div = (
<div>
<h1>H1</h1>
<h2>H2</h2>
</div>
)
2、变量使用花括号
const id = 1
const name = "杜恒"
const Div = <div data-id={id}>{name}</div>
3、外连样式与内联样式
// 使用class时,需要写className的方式
const Div = <div className="box"></div>
// 内联样式时,需要成变量内包对象方式
const Div2 = <div style={{ color: '#ff6800', fontSize: '30px' }}>Test</div>
4、单标签需要闭合
const div = (
<div>
<br />
<input />
</div>
)
5、循环数组
const arr = ['vue', 'react', 'jquery']
const Ul = (
<ul>
{ arr.map(item => <li key={item}>{item}</li>) }
</ul>
)
组件
1、函数式组件(简单组件<在hooks里面可以实现3大属性>)
function Test() {
console.log(this) // undefined
return <div>Test组件</div>
}
ReactDOM.render(<Test />, document.querySelector("#main"))
2、类式组件(复杂组件)
class Test extends React.Component {
render() {
console.log(this); // 由Test类创造的组件实例对象
return <div>Test组件</div>
}
}
/*
*
* 首先解析Test标签,并找到Test的类
* 接着React内部,会去new这个Test类,接着会初始化实例对象上的render方法
*
*/
ReactDOM.render(<Test />, document.querySelector("#main"))
组件实例三大属性 state
class Weather extends React.Component {
render() {
console.log(this);
return <h1>今天天气很炎热</h1>
}
}
ReactDOM.render(<Weather />, document.querySelector("#main"))
打印类的实例对象上的this,可以看到实例对象身上挂了一个state属性,默认值为null
class Weather extends React.Component {
/* constructor根据页面上有多少个实例就调用几次 */
constructor(props) {
super(props)
/* 向当前实例上挂载一个属性 */
this.state = { isHot: false }
/* 解决changeWeather中的this指向undefined的问题 */
this.changeWeather = this.changeWeather.bind(this)
}
/* render调用1 + n次,第一次进入默认执行一次,后state更新触发render */
render() {
/* this指向当前的实例,于是可以通过this访问到state属性 */
console.log(this);
/* onClick绑定的函数不能加括号,否则会直接执行函数! */
return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot ? '炎热' : '凉爽'}</h1>
}
/*
*
* changeWeather挂载在Weather的原型对象上,供Weather的实例对象使用,
* 只有Weather的实例对象去调用这个方法,函数内的this才会指向Weather的实例对象
* 由于在class中会将函数开启局部严格模式,因此changeWeather里的this会指向undefined
* 但需要解决这个this指向问题,因此就需要在上方初始化的时候,改变this的指向
*
*/
changeWeather() {
console.log(this);
/*
* 状态不可直接更改!
* this.state.isHot = !this.state.isHot ×
*/
this.setState({
isHot: !this.state.isHot
})
}
}
ReactDOM.render(<Weather />, document.querySelector("#main"))
上面的代码可以简写成下方代码
class Weather extends React.Component {
// 直接赋值给实例化对象身上
state = { isHot: false }
// 直接赋值给实例化对象身上
changeWeather = () => {
console.log(this); // this 指向当前实例化后的对象
this.setState({ isHot: !this.state.isHot })
}
render() {
return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot ? '炎热' : '凉爽'}</h1>
}
}
ReactDOM.render(<Weather />, document.querySelector("#main"))
组件实例三大属性 props
1、props的基本使用
class Person extends React.Component {
render() {
return <h1 data-age={this.props.age} data-sex={this.props.sex}>{this.props.name}</h1>
}
}
const person = {
age: 18,
sex: "男"
}
ReactDOM.render(<Person name="杜恒" {...person} />, document.querySelector("#main"))
2、props属性限制
class Person extends React.Component {
/* 限制props传入的类型 */
static propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
sex: PropTypes.string
}
/* props未传的时候的默认值 */
static defaultProps = {
age: 18,
sex: "男"
}
render() {
return (
<ul>
<li>姓名:{this.props.name}</li>
<li>年龄:{this.props.age}</li>
<li>性别:{this.props.sex}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="杜恒" age={23} />, document.querySelector("#main"))
3、定义组件时,如果写了构造器,需要将props传递给父类,否则可能会出现找不到 this.props 的bug
class Person extends React.Component {
constructor() {
super()
console.log(this.props); // undefined
}
render() {
return <h1>{this.props.name}</h1>
}
}
4、函数式组件接收props
function Person(props) {
console.log(props);
return <h1>{props.name}</h1>
}
ReactDOM.render(<Person name="杜恒" />, document.querySelector("#main"))
组件实例三大属性 refs
1、字符串形式的 ref (已废弃)
class Test extends React.Component {
/* 点击显示左侧input的内容 */
showInputValue = () => {
console.log(this);
alert(this.refs.input.value)
}
showBlurInputValue = e => {
e.persist();
console.log(e);
alert(e.target.value)
}
render() {
return (
<ul>
<li>
<input ref="input" type="text" />
<button onClick={this.showInputValue}>点击显示左侧提示</button>
</li>
<li>
<input onBlur={this.showBlurInputValue} type="text" placeholder="失去焦点弹出提示" />
</li>
</ul>
)
}
}
2、回调函数形式的 ref
class Test extends React.Component {
showInputValue = () => {
console.log(this.input);
alert(this.input.value)
}
render() {
return (
<div>
<input ref={node => (this.input = node)} type="text" />
<button onClick={this.showInputValue}>点击显示左侧提示</button>
</div>
)
}
}
内联方式的ref里的回调函数,在更新状态的时候,会触发2次,第一次会得到null,第二次才得到当前的节点,如果想避免这个问题,可以将函数写成class的方式,上面的方式可以写成下面这种
class Test extends React.Component {
/* 点击显示左侧input的内容 */
showInputValue = () => {
console.log(this.input);
alert(this.input.value)
}
/* 保存input */
saveInputRef = (node) => {
this.input = node
}
render() {
return (
<div>
<input ref={this.saveInputRef} type="text" />
<button onClick={this.showInputValue}>点击显示左侧提示</button>
</div>
)
}
}
3、createRef 形式
class Test extends React.Component {
myRef = React.createRef()
/* 点击显示左侧input的内容 */
showInputValue = () => {
console.log(this.myRef);
alert(this.myRef.current.value)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" />
<button onClick={this.showInputValue}>点击显示左侧提示</button>
</div>
)
}
}
ReactDOM.render(<Test />, document.querySelector("#main"))
很奈斯