(1) propTypes库
(官网)http://www.css88.com/react/docs/typechecking-with-proptypes.html
propTypes :在组件中进行props的类型检测
isRequired关键字:用来强制组件某个参数必须传入
PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string
PropTypes.node
PropTypes.element
- (1) 安装
npm install prop-types --save
- 引入
import propTypes from 'prop-types'
- (2) 使用
import React, {Component} from 'react'
import propTypes from 'prop-types' // 引入prop-tyes库
export default class Header extends Component {
render() {
return (
<div className="headers">
<h1>react.js小树标题{this.props.a.name1}</h1>
</div>
)
}
}
Header.propTypes = { // 使用prop-types库
a: propTypes.object // a的propTypes类型是对象类型
// a: propTypes.object.isRequired // isRequired关键字来强制组件某个参数必须传入
}
Header.defaultProps = { // 指定 props 的默认值:
a: {
name1: 'Li'
}
};
------------------------------------------------------------------------------
也可以写在里面:
import React, {Component} from 'react'
import propTypes from 'prop-types' // 引入prop-tyes库
export default class Header extends Component {
static propTypes = { // 使用prop-types库
a: propTypes.object
}
static defaultProps = { // 指定 props 的默认值:
a: {
name1: 'WU'
}
}
render() {
return (
<div className="headers">
<h1>react.js小树标题{this.props.a.name1}</h1>
</div>
)
}
}
(2) Context上下文
(官网)http://www.css88.com/react/docs/context.html
(1) childContextTypes
验证 getChildContext 返回的对象类型
- 为什么要验证 context,因为 context 是一个危险的特性,按照 React.js 团队的想法就是,把危险的事情搞复杂一些,提高使用门槛人们就不会去用了。如果你要给组件设置 context,那么 childContextTypes 是必写的。
static childContextTypes = {
themColor: propTypes.string
}
(2) getChildContext()
getChildContext() 这个方法就是设置 context 的过程,它返回的对象就是 context,所有的子组件都可以访问到这个对象
- 某个组件只要往自己的 context 里面放了某些状态,这个组件之下的所有子组件都直接访问这个状态而不需要通过中间组件的传递。一个组件的 context 只有它的子组件能够访问,它的父组件是不能访问到的,你可以理解每个组件的 context 就是瀑布的源头,只能往下流不能往上飞。
getChildContext() {
return {
themColor: this.state.themColor
}
}
(3) 父组件存context,子组件取context
- 注意:子组件必须验证context的propTypes否则,context不会生效
父组件:index.js
(1) 验证context类型
(2) 存context
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import Header from './Header'
import Content from './Content'
import './index.css'
import propTypes from 'prop-types'
class Index extends Component {
static childContextTypes = { // 验证context类型
themColor: propTypes.string
}
constructor(props) {
super(props)
this.state = {
themColor: 'olive'
}
}
getChildContext() { // 存context
return {
themColor: this.state.themColor
}
}
render () {
return (
<div>
<Header/>
<Content />
</div>
)
}
}
ReactDOM.render(
<Index />,
document.getElementById('root')
)
-------------------------------------------------------------------------------
子组件 themeSwitch.js
(1) 验证context类型
(2) 取context
import React, {Component} from 'react'
import propTypes from 'prop-types'
export default class ThemeSwitch extends Component {
static contextTypes = { // 验证context类型
themColor: propTypes.string
}
render() {
return (
<div> // 取context
<h1 style={{color: this.context.themColor}}>这是context共享的颜色olive</h1>
<button>red</button>
<button>blue</button>
</div>
)
}
}
(3) onContextMenu 右键菜单 ( 上下文菜单 )
- (1) 使用:
1.阻止默认事件: e.preventDefault()
2.阻止冒泡事件: e.stopPropagation()
3.鼠标相对浏览器位置计算: e.clientX 和 e.clientY
4.取消右键菜单: 点击鼠标左键,右键来取消右键菜单
import React, {Component} from 'react'
import CommentInput from './commentInput'
import CommentList from './commentList'
class CommentApp extends Component {
constructor(props) {
super()
this.state = {
comments: [],
y:0,
x:0,
showContextMenu: false,
}
}
handleSubmitComment(value) {
this.state.comments.push(value)
this.setState({
comments: this.state.comments
})
}
onRightMenu = (e) => { // 右键时执行的方法
this.setState({
y: e.clientY, // 鼠标位置
x: e.clientX,
showContextMenu: true, // 显示浮层
})
e.preventDefault() // 阻止默认
e.stopPropagation() // 阻止冒泡
}
leftClickCancel = () => { // 左击取消
this.setState({
showContextMenu: false,
})
}
rightClickCancel = (e) => { // 右击取消
this.setState({
showContextMenu: false,
})
e.preventDefault()
e.stopPropagation()
}
render() {
return (
<div className='wrapper'>
<CommentInput onSubmit={this.handleSubmitComment.bind(this)}/>
<CommentList comments={this.state.comments}/>
<div className='context' onContextMenu={(e) => this.onRightMenu(e)}>
查看更多
</div>
<div
className='totalMenuWrapper'
style={ this.state.showContextMenu ? {display:'block'} : {display: 'none'}}
onClick={this.leftClickCancel}
onContextMenu={ (e) => this.rightClickCancel(e)}
>
<div className='menuWrapper' style={{top:this.state.y, left: this.state.x}}>
<div className='contextMenuList'>菜单一</div>
<div className='contextMenuList'>菜单二</div>
<div className='contextMenuList'>菜单三</div>
</div>
</div>
</div>
)
}
}
export default CommentApp
效果图
(4) 对象
(1)对象的声明方法 ( 三种 )
- {} 直接生成
- new Object()
- Object.create()
声明对象的三种方法:
var o1 = {};
var o2 = new Object();
var o3 = Object.create(Object.prototype);
上面三行语句是等价的。一般来说,
第一种采用大括号的写法比较简洁,
第二种采用构造函数的写法清晰地表示了意图,
第三种写法一般用在需要对象继承的场合。
(2) 键名 :对象的所有键名都是字符串 ( 键名:键值 )
- 对象的所有键名都是字符串,所以加不加引号都可以。
(3) 属性 : 对象的每一个“键名”又称为“属性”(property)
- 对象的每一个“键名”又称为“属性”(property),它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用。
- 对象的属性之间用逗号分隔,最后一个属性后面可以加逗号(trailing comma),也可以不加。
(4) 读取属性 : 两种方法 ( 点运算符和方括号运算符 )
- 读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。
var o = {
p: 'Hello World'
};
o.p // "Hello World"
o['p'] // "Hello World"
上面代码分别采用点运算符和方括号运算符,读取属性p。
请注意:
如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。
但是,数字键可以不加引号,因为会被当作字符串处理。
- 方括号运算符内部可以使用表达式。
o['hello' + ' world']
o[3 + 3]
(5) 赋值属性:
- 点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。
o.p = 'abc';
o['p'] = 'abc';
上面代码分别使用点运算符和方括号运算符,对属性p赋值。
JavaScript允许属性的“后绑定”,也就是说,你可以在任意时刻新增属性,没必要在定义对象的时候,就定义好属性。
(6) Object.keys() 方法 :查看所有属性,返回的是数组
- Object.keys() 返回的是所有属性(键名)组成的数组
var o = {
key1: 1,
key2: 2
};
Object.keys(o);
// ['key1', 'key2']
(7) delete命令 : 删除对象的属性,返回boolean布尔值
- delete命令用于删除对象的属性,删除成功后返回true。
- 注意,删除一个不存在的属性,delete不报错,而且返回true。
var o = {p: 1};
Object.keys(o) // ["p"]
delete o.p // true
o.p // undefined
Object.keys(o) // []
------------------------------------------------------------
var o = {};
delete o.p // true
上面代码中,o对象并没有p属性,但是delete命令照样返回true。
因此,不能根据delete命令的结果,认定某个属性是存在的,只能保证读取这个属性肯定得到undefined。
(8) in运算符 : 检查对象是否包含某个属性,检查的是键名,返回的是boolean布尔值
- in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true,否则返回false。
- in运算符的一个问题是,它不能识别对象继承的属性。
var o = { p: 1 };
'p' in o // true
// 假设变量x未定义
// 写法一:报错
if (x) { return 1; }
// 写法二:不正确
if (window.x) { return 1; }
// 写法三:正确
if ('x' in window) { return 1; }
(9) for…in循环 : 遍历一个对象的所有属性
- for...in循环用来遍历一个对象的全部属性。
- for...in循环有两个使用注意点:
它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性
它不仅遍历对象自身的属性,还遍历继承的属性。
for(let i in xx) 遍历一个对象的所有属性
var o = {a: 1, b: 2, c: 3};
for (var i in o) {
console.log(o[i]);
}
// 1
// 2
// 3
---------------------------------------------------
提取对象属性(重点)(重点)(重点)(重点)(重点)(重点)(重点)
var obj = {
x: 1,
y: 2
};
var props = [];
var i = 0;
for (props[i++] in obj);
props // ['x', 'y']
---------------------------------------------------
var obj = {
x: 1,
y: 2
};
let gg = []
for (let i in obj) {
gg.push(i)
}
console.log(gg) // ["x", "y"]
(10) 检查变量是否声明
- 如果读取一个不存在的键,会返回undefined,而不是报错。可以利用这一点,来检查一个全局变量是否被声明。
if ('a' in window) {
// 变量 a 声明过
} else {
// 变量 a 未声明
}
(5) Object对象
(1) 概述
- JavaScript 原生提供Object对象(注意起首的O是大写),所有其他对象都继承自这个对象。Object本身也是一个构造函数,可以直接通过它来生成新对象。
- 两点:
1.所有其他对象都继承自Object对象
2.Object自身也是一个构造函数,可以直接通过它来生成新对象
var obj = new Object();
-----------------------------------------
Object作为构造函数使用时,可以接受一个参数。
如果该参数是一个对象,则直接返回这个对象;
如果是一个原始类型的值,则返回该值对应的包装对象。
var o1 = {a: 1};
var o2 = new Object(o1); // Object构造函数,可接受一个参数
o1 === o2 // true // 参数是对象,则直接返回对象
new Object(123) instanceof Number // 参数是原始类型的值,返回该值对应的包装对象
// true
(2) 与其他构造函数一样,如果要在Object对象上面部署一个方法,有两种做法。
- (1)部署在Object对象本身
比如,在Object对象上面定义一个print方法,显示其他对象的内容。
Object.print = function(o){ console.log(o) };
var o = new Object();
Object.print(o)
// Object
- (2)部署在Object.prototype对象
所有构造函数都有一个prototype属性,指向一个原型对象。凡是定义在Object.prototype对象上面的属性和方法,将被所有实例对象共享。
Object.prototype.print = function(){ console.log(this)};
// es6写法:Object.prototype.print = () => { console.log(this) }
var o = new Object();
o.print() // Object
上面代码在Object.prototype定义了一个print方法,然后生成一个Object的实例 o。
o直接继承了Object.prototype的属性和方法,可以在自身调用它们,
也就是说,o对象的print方法实质上是调用Object.prototype.print方法
可以看到,尽管上面两种写法的print方法功能相同,但是用法是不一样的,因此必须区分“构造函数的方法”和“实例对象的方法”。
(3) Object()
- Object本身当作工具方法使用时,可以将任意值转为对象。这个方法常用于保证某个值一定是对象。
(4) Object 对象的静态方法
- 所谓“静态方法”,是指部署在Object对象自身的方法。
-
Object.keys(),Object.getOwnPropertyNames()
- Object.keys方法只返回可枚举的属性
- Object.getOwnPropertyNames方法还返回不可枚举的属性名。
- Object.keys方法和Object.getOwnPropertyNames方法很相似,一般用来遍历对象的属性。它们的参数都是一个对象,都返回一个数组,该数组的成员都是对象自身的(而不是继承的)所有属性名。它们的区别在于,Object.keys方法只返回可枚举的属性(关于可枚举性的详细解释见后文),Object.getOwnPropertyNames方法还返回不可枚举的属性名。
-
一般情况下,几乎总是使用Object.keys方法,遍历数组的属性。
var o = {
p1: 123,
p2: 456
};
Object.keys(o)
// ["p1", "p2"]
Object.getOwnPropertyNames(o)
// ["p1", "p2"]
上面的代码表示,对于一般的对象来说,这两个方法返回的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果
------------------------------------------------------------------
var a = ["Hello", "World"];
Object.keys(a)
// ["0", "1"]
Object.getOwnPropertyNames(a)
// ["0", "1", "length"]
上面代码中,数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。
------------------------------------------------------------------
Object.keys(o).length
Object.getOwnPropertyNames(o).length
由于JavaScript没有提供计算对象属性个数的方法,所以可以用这两个方法代替。
网友评论