React入门(个人学习笔记)

运行环境

  • Node.js
  • React库
  • sublime-text
创建一个React项目

在workspace目录下打开cmd窗口,依次输入:

create-react-app react-demo  (react-demo项目名)

cd react-demo 

npm install

npm start     //运行

运行成功,弹出react-demo的欢迎页面.

代码

进入 react-demo/src 目录,以下是注释:

自动生成的代码

index.js

负责渲染 react-demo/public/index.html (即欢迎页面)

import React from 'react';//核心库
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';//导入根组件(App)
import * as serviceWorker from './serviceWorker';//负责快速渲染

//向index.html部署根组件
//html中有一个id为'root'的div标签
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();

App.js

根组件;通过向其添加子组件完成UI设计

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <div>
      <h2>你好,根组件</h2>
      </div>
    </div>
  );
}

export default App;

App.js:(更改后)

import Home from './Home'  /*---引入子组件---*/

function App() {
  return (
    <div className="App">
	
      <Home />  /*---添加子组件---*/

    </div>
  );
}
export default App;

手动生成

Home.js

子组件;
格式如下:
整体上是ES6的class模板
前半段为js语法;后半段(render)为JSX语法(JavaScript+html);
通过 render()方法展示视图的层次结构;
在JSX中,用{}把JavaScript 表达式括起来,{}之外写html代码

import React from 'react';
import logo from './nothing.jpg';//导入图片


class Home extends React.Component{//ES6终于引入了class概念
	constructor(props){
		super(props);
		this.state={
			input:'张三',
			name:'李四'
		}

	}
	
	print(){//自定义方法
	alert(this.state.input);
	}

	setName(newName){//自定义方法
		this.setState({name:newName});
	}

	render(){//模板!
		return(//JSX语法
			<div>
			<p />{this.name}<br />
			<img src={logo} alt="logo"/><br/>
			<img src="https://www.baidu.com/img/dong_18baaa7524814ab080a65d15e2da33fd.gif" alt=""/>
			<hr/>
			<br />
			<button onClick={this.print.bind(this)}>执行print方法</button>
			<br />
			<button onClick={this.setName.bind(this,'新的名字!')}>执行setName方法</button>//鼠标点击事件


			</div>
		)
	}
}

export default Home;//方能被APP.js识别

注意:

  1. render中先整个div,把所有内容写到里面;
  2. 修改state必须交给setState()来完成;
  3. 在以类继承的方式定义的组件中,通常需要将事件处理函数中的this指向当前组件实例。

如何让this指向当前组件实例?

方法1:在标签中使用bind()函数

 	run(){
       	alert(this.state.name);
 	}
 	...
 	<button onClick={this.run}>按钮</button>//错误写法
 	<button onClick={this.run.bind(this)}>按钮</button>

解释:button组件中的this指向当前这个组件实例;
但当外部环境运行到这里,调用run函数时,就会丢失这个this指向(组件实例);
函数中的this会被解释为指向这个外部环境,虽然其本意是指向组件实例;
所以需要bind函数;
它会以创建它时传入bind方法的第一个参数作为函数的this

方法2:箭头函数

run=()=>{
	alert(this.state.name);
}
...
<button onClick={this.run}>按钮</button>

解释:箭头函数内部的this是词法作用域,由上下文确定;
即箭头函数内部的this总是指向词法作用域,即外层调用者

问答环节

1问:点击一个按钮,然后如何获取这个按钮的某些属性(比如id)?
答:

run(event){
		var id = event.target.getAttribute('id');// biu
		alert(id);
	}
...
render(){
	return(
		<button id = 'biu' onClick={this.run.bind(this)}>运行run方法</button>
	)
}

2问:如何将输入框的文本信息传到后台?
答:

方法1:通过事件获取输入信息

	inputChange(event){
		var val = event.target.value;
		this.setState({userName:val})
	}
	...
	<input type="text" onChange={this.inputChange.bind(this)} />

方法2:获取dom节点——通过设置属性’ref’获取输入信息

	inputChange(){
		var val = this.refs.userName.value;
		this.setState({userName:val})
	}
	...
	<input type="text" ref='userName' onChange={this.inputChange.bind(this)} />

3问:如何让可以监听键盘敲击事件?且键入回车就传值?
答:

	inputKeyDown(e){
		if(e.keyCode === 13){//如果敲击了回车键
			var val = e.target.value;
			this.setState({userName:val});
			e.target.value='';
		}
	}
	...
	<input type="text" onKeyDown={this.inputKeyDown.bind(this)} />//onKeyUp也行

注意:event事件和view是双向绑定的;
所以可以通过event事件反过来影响视图(上面重置了输入框的value)

4问:如何实现双向数据绑定?(view <==> model)
答:

  1. value属性绑定数据;
  2. 实现onChange()方法(必须实现);

设置defaultValue属性并不能动态刷新view

	change(e){
		var val = e.target.value;
		this.setState({userName:val});
	}
	...
	<input type="text" value={this.state.userName} onChange={this.change.bind(this)}/>

常用标签

  • 单选标签
changeSex(e) {
	var val = e.target.value;
	this.setState({
		sex: val
	});
}
...
<input type="radio" value='男' checked={this.state.sex=='男'} onChange={this.changeSex.bind(this)}/><input type="radio" value='女' checked={this.state.sex=='女'} onChange={this.changeSex.bind(this)}/>

注意:checked属性为true,则显示选中;为false,显示不选中

  • 选择列表select

<select>
  
/*JSX*/
this.state = {
	city: 'defaultCity',
	citys: ['成都', '北京', '深圳']
}
...
handleChange(e) {
	var val = e.target.value;
	this.setState({
		city: val
	})
}
...
<select value={this.state.city} onChange={this.handleChange.bind(this)}>
{this.state.citys.map(function(value,key){return <option key={key}>{value}</option>; })}

</select>
<button type='submit'>确认</button>
<br/>
{this.state.city}
<h2>new</h2>
<select>
  1. 循环数据时若出现标签,则必须绑定key属性;
  2. 解释:数组的map方法:

Array.map(function(index1,index2)):
结果:返回一个新的数组;
计算方法:新数组的每个元素由原来的每个元素调用function得到;
按顺序,第一个index获取元素的值,第二个index获取元素的下标

React入门(个人学习笔记)_第1张图片

  • 复选框checkbox
/*JSX*/
this.state = {
	hobby: [{
		'title': '睡觉',
		'checked': true
	}, {
		'title': '吃饭',
		'checked': false
	}, {
		'title': '打豆豆',
		'checked': true
	}]
}
...
handleHobby(key) {
	var hobby = this.state.hobby;
	hobby[key].checked = !hobby[key].checked;
	this.setState({
		hobby: hobby
	});
	console.log(this.state.hobby);
}
...	
{
	this.state.hobby.map((value,key)=>{
		return (
		<span key={key}>
		{value.title}<input type="checkbox" checked={value.checked} onChange={this.handleHobby.bind(this,key)}/>
		</span> )
	})
}

注意return的形式!return的代码最好全写在一个根节点中

这里写图片描述

父组件向子组件传值

以Home.js为父组件,Header.js为子组件 为例:

1.在调用子组件的时候定义一个属性


2.子组件里面 {this.props.msg}
说明:父组件不仅可以给子组件传值,还可以给子组件传方法,以及把整个父组件传给子组件。

如果父组件调用子组件的时候不给子组件传值,可以在子组件中使用defaultProps定义的默认值

{this.props.title}//网页成功显示"标题"

Header.defaultProps = {//在class外部
	title: '标题'
}

propTypes:在子组件中验证父组件传值的类型合法性

//Home.js
...
<Header name=123 />
...
//Header.js
import PropTypes from 'prop-types';
...
Header.propTypes = {//在class外部
	name: PropTypes.string
}

结果:网页运行报错(期待string类型,而传入了number类型)

你可能感兴趣的:(React入门(个人学习笔记))