import 导入&export 导出
- 备注:想要导入某个组件,必须先导出
- 自定义组件首字母必须大写,否则报错
// 示例1:导入
import App from "./App.js"; //从App.js文件中导入App组件;.js后缀可省略
import "./index.css";
// 示例2:导出
export default App;
class 类比
- class 的方法和原始的 function 上下文是一致的
- class 中的静态方法不能访问非静态属性
- class 的静态属性并有兼容性或者说支持性不好
// 示例1:function模式
function Person() {}
var p = new Person();
Person.prototype.age = 1; // 定义实例属性 或者 p.age = 1
Person.prototype.say = function() {}; // 定义实例方法 或者 p.say = function(){}
P.age = 10; // 定义静态属性
P.say = function() {}; // 定义静态方法
// 示例2:class模式
class Person {
age = 1; //实例属性
say() {} //实例方法
static staticAge = 999; //静态属性
static staticFun = function() {}; //静态方法
}
var p = new Person();
p.say();
Person.staticFun();
p.staticFun();
JSX 语法
- JSX:js+html(遇见
<
就当做 html 解析 {
当做 js 解析 )
JSX 注释
// 方式1:推荐
{/* JSX注释 */}
// 方式2:
{
// JSX注释
}
基本操作总结
- 引入 React 对象
- 引入 ReactDom 对象
-
- 操作 JSX
- 渲染到指定的元素上:
ReactDom.render(<App />, document.getElementById('root'));
- 启动
npm start
【必须在项目目录下执行】
编写 App 渲染内容
- render 函数返回渲染只能有一个根节点
-
<Fragment>
:没有节点含义,可以包含其他元素
// 示例1:
class Xiaojiejie extends Component {
render() {
return (
// 这里Fragment 没有节点含义,但是render返回必须保证一个根节点
<Fragment>
<input /> <button>add</button>
<ul>
<li>岳不群</li>
<li>东方不败</li>
</ul>
</Fragment>
);
}
}
react 中有变化的属性
- 节点的 class 属性需要写
className
- 节点的 for 属性需要写
htmlFor
// 示例1:将lable和input关联起来,只要点击lable内容,鼠标就会直接定位到输入框
<label htmlFor="inputIterm" >增加项目</label>
<input id="inputIterm"
value={this.state.inputValue}
onChange={this.changeHandler.bind(this)}
/>
- 事件名字采用驼峰式;并且使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串
// 示例2:事件名字采用驼峰式;并且传入函数而不是字符串
<button onclick="activateLasers()">
Activate Lasers
</button>
// react写法
<button onClick={activateLasers}>
Activate Lasers
</button>
- 在
React
中不能通过返回 false
的方式阻止默认行为, 必须显式的使用 preventDefault
// 示例3:
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
// react写法
function ActionLink() {
function handleClick(e) {
e.preventDefault(); // 显示preventDefault
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
- 事件处理函数的参数传递问题:
- 箭头函数写法的
事件对象e
必须显示传递
- 通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递
// 示例1:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
// bind形式的 e 参数是被隐式传递的
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
函数调用 this 指向
- this:在 react 中或者说在 es6 的类中如果获取到成员函数的地址直接调用函数,则函数内部的 this 并不指向 window,而是指向 undefined(由于 class 内部是
严格模式
,所以 this 实际指向的是undefined)
// 示例1:
class AAA{
say(){
// 在es6中全局this指向undefined;在es5中指向window或者说全局环境
console.log(this);
}
say2(func){
// this指向AAA的实例对象
console.log(this);
func();
}
tt(){
console.log(this);
}
}
let a = new AAA();
a.say2(a.say); // 此时es6中say方法中的this指向undefined;es5中的this指向window
var ff = a.tt;
ff(); // es6中此时ff中的this指向undefined;es5中的this指向window
// 方式1:构造函数中绑定函数this指向
constructor(){
this.say = this.say.bind(this);
}
// 方式2:在行内直接绑定
onClick = addHandle.bind(this)
// 方式3:使用箭头函数 箭头函数的this指向取决于上层作用域的this
onClick = ()=>{ }
// 或者如下
onClick = addHandle
addHandle = ()=>{}
数据绑定
- 数据存放在
this.state
对象中;可以直接读取,但是不能直接修改赋值;只能通过this.setState({})
方法操作state中的数据
// 示例1:
this.state = {
inputValue: "",
list: []
}
// 删除list指定下标元素
deleteHandler(index){
let list = this.state.list;
list.splice(index, 1);
this.setState({
list: list
})
// 不能直接操作this.state.list
// this.state.list.splice(index, 1);
// this.setState({
// list: this.state.list
// })
}
dangerouslySetInnerHtml解析内容的样式
- 可以将需要展示的内容中样式解析出来(比如iterm是 <h2>aaa</h2>, 可以解析h2标签)
// 示例1:
<li
key={index + iterm}
onClick={this.deleteHandler.bind(this, index)}
dangerouslySetInnerHTML={{__html: iterm}}
>
{/* {iterm} */}
</li>
列表 & Key
渲染多个组件
// 示例1:listItems数组的每个元素都是li标签
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number} </li>
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
key
- key 只是在兄弟节点之间必须唯一;应当给数组中的每一个元素赋予一个确定的标识;key 帮助 React 识别哪些元素改变了,比如被添加或删除
- 一般都是给数组的每项元素添加key用于标识
// 示例2:key
function ListItem(props) {
// 正确!这里不需要指定 key:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 正确!key 应该在数组的上下文中被指定
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
在 JSX 中嵌入 map()
- JSX 允许在大括号中嵌入
任何表达式
;注意嵌入是表达式而不是语句
- 心得:可以在
{}
中写 三目运算表达式或者判断表达式
// 示例1:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
// 示例2:
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
// 示例3:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
);
}
this.props.children
- this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点
// 示例1:
var NotesList = React.createClass({
render: function() {
return (
<ol>
{
React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})
}
</ol>
);
}
});
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.body
);
// 解析:this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。
// React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object
PropTypes类型检查 & getDefaultProps
- 组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求
// 示例1:
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ref属性
- 有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性
react表单
受控组件和非受控组件
传递参数及 DOM
问题
- 不使用 jsx 中的 html 标签,怎么使用 React.createMent 写