React 属性和状态详解
最后更新于:2022-04-01 11:56:50
### 属性的含义和用法
props=properties
属性:一个事物的性质与关系
属性往往是与生俱来的、无法自己改变的.
属性的用法:
**第一种方法:键值对**
1、传入一个字符串:”Hi”(字符串)/{“Hi”};
2、传入一个数组{[arry]};
3、传入一个变量{variable}
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var HelloWorld = React.createClass({
render: function () {
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
}
});
var HelloUniverse = React.createClass({
getInitialState: function () {
return {name: ""};
},
handleChange: function (event) {
this.setState({name: event.target.value});
},
render: function () {
return(
<div>
<HelloWorld name = {this.state.name}></HelloWorld>
<input type = "text" onChange = {this.handleChange}/>
</div>
)
}
});
ReactDOM.render(<HelloUniverse></HelloUniverse>, document.querySelector("#example"));
</script>
~~~
运行结果如下,使用的是键值对的方式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_57060400aea35.jpg)
**第二种方法:可以理解为展开**
var props = {one:”hello”, two:”message”}
React提供展开语法…,使用…加对象,react就会把对象中的属性和值,当成是属性的赋值:
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var HelloWorld = React.createClass({
render: function () {
return <p>Hello, {this.props.name + " " + this.props.age}</p>;
}
});
var HelloUniverse = React.createClass({
getInitialState: function () {
return {name: "Yvette", age: "25"};
},
handleChange: function (event) {
this.setState({name: event.target.value});
},
render: function () {
return(
<div>
<HelloWorld {...this.state}></HelloWorld>
<input type = "text" onChange = {this.handleChange}/>
</div>
)
}
});
ReactDOM.render(<HelloUniverse></HelloUniverse>, document.querySelector("#example"));
</script>
~~~
运行结果如下,使用{…this.state}展开
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_57060400c1605.jpg)
**第三种方法:调用react提供的setProps函数**
setProps接收的参数是一个对象,但是react不推荐改变组件的属性,可以通过父组件向子组件传入的方式。
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var HelloWorld = React.createClass({
render: function(){
return <p>Hello, {this.props.name}</p>
}
});
var instance = ReactDOM.render(<HelloWorld></HelloWorld>, document.querySelector("#example"));
instance.setProps({name: "William"});
</script>
~~~
使用setProps修改属性值,此种方式不推荐,如果需要改变属性值,可以参考第一个例子,利用父组件去修改。
### 状态的含义和用法
state
状态:事物所处的状况。
状态是由事物自行处理、不断变化的。
状态是事物的私有属性。
状态的用法
getInitialState:初始化每个实例特有的状态
setState:更新组件状态
使用setState——启用diff算法——有变化,更新DOM
### 属性和状态的对比
属性和状态的相似点
1、都是纯JS对象
2、都会触发render更新
3、都具有确定性
状态只和组件本身相关,组件不能修改属性
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_57060400d30ae.jpg)
组件在运行时需要修改的数据就是状态。
### 属性和状态的实例
编写一个简单的文章评论框
第一步:分析构成项目的组件
第二步:分析徐俊的关系和数据传递
第三步:编写代码
第一步:分析构成项目的组件
评论框
内容
第二步:分析徐俊的关系和数据传递
评论框是内容的父组件
父组件需要传递评论对象子组件,评论对象是内容组件的属性,评论内容是内容组件的状态。
1、select,option是写死的
2、option的内容应该是动态的,将option的内容作为状态提取出来
利用属性和状态实现一个评论框:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title>评论框</title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<!--将option提取出来作为父组件的状态-->
<!--将评论对象(selectName)传递给子组件-->
<!--修改子组件,构建回复内容-->
<!--监听内容的变化,并将变化记录在状态中-->
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var style = {
width:300 + 'px',
height:150 + 'px',
marginTop:20+'px',
marginBottom:20+'px',
resize: 'none',
textIndent:10 + 'px'
};
var Content = React.createClass({
getInitialState: function (){
return{
inputText: ""
};
},
handleChange: function(event){
this.setState({inputText:event.target.value})
},
handleSubmit: function () {
console.log("reply to: " + this.props.selectName + "\n" + this.state.inputText);
},
render: function () {
return (<div>
<textarea style = {style} onChange = {this.handleChange} placeholder = "please enter something..." ></textarea>
<br/>
<button onClick = {this.handleSubmit}>submit</button>
</div>);
}
});
var Comment = React.createClass({
getInitialState: function () {
return{
names: ["William", "Yvette", "Katharine"],
selectName: ""
};
},
handleChange: function (event) {
this.setState({selectName:event.target.value})
},
render: function () {
var options = [];
for(var option in this.state.names){
options.push(<option value = {this.state.names[option]}> {this.state.names[option]} </option>)
};
return (
<div>
<select onChange = {this.handleChange}>
{options}
</select>
<Content selectName = {this.state.selectName}></Content>
</div>);
}
});
ReactDOM.render(<Comment></Comment>, document.querySelector("#example"));
</script>
~~~
需要注意的是,React中,style不能直接写300px,需要使用拼接,另外margin-top等也需要使用驼峰命名法,写成marginTop
运行结果如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_57060400ea0d5.jpg)
ReactJS组件生命周期详述
最后更新于:2022-04-01 11:56:48
前面已经写了一篇关于reactJS组件生命周期的博文,此篇博文是一个补充,增加了一些例子,有助于更好的理解reactJS组件。
**初始化阶段能够使用的钩子函数(按照触发顺序):**
**getDefaultProps**(获取实例的默认属性)————只有第一次实例的时候调用,实例之间共享引用(属性)
**getInitialState**(获取实例的初始状态)————初始化每个实例特有的状态
必须返回一个Object或者是Null
**componentWillMount**(组件即将被渲染到页面)——render之前最后一次修改状态的机会
**render**(组件在render中生成虚拟的DOM节点,即JSX,最后由React生成真实的DOM节点)——只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。
如果render需要修改状态和DOM输出,那么render就不能在服务端使用。并且,如果在render中修改状态和DOM输出,会使得代码逻辑变得复杂。所以,要尽可能避免这样做。
**componentDidMount**(组件被渲染到页面之后)——成功render并渲染完成真实DOM之后触发,可以修改DOM
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
<div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var MyComponent = React.createClass({
getDefaultProps: function(){
console.log("获取实例的默认属性");
return{name: "Yvette"};
},
getInitialState: function () {
console.log("获取实例的初始状态");
return{will:true};
},
componentWillMount: function () {
console.log("组件即将被渲染到页面");
},
handleClick: function(event){
this.setState({will: !this.state.will});
},
componentDidMount: function(){
console.log("aaaa");
if(this.state.will){
$(this.refs.example).append("啦啦啦");
}else{
$(this.refs.example).append("郁闷");
}
},
render: function(){
console.log("render");
return(
<div>
<p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
</div>
)
}
});
ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_5706040076301.jpg)
从运行结果可以看出:
1、获取默认属性(getDefaultProps)只会在第一次实例化组件时运行一次,后面不会再运行,
2、获取初始状态(getInitialState)和componentWillMount,render,componentDidMount在每次实例化组件时,都会进入.
3、点击切换时,只会触发render函数,因此我们写在componentDidMount函数中的状态判断不会再被执行.
**运行中阶段能够使用的钩子函数(按照触发顺序):**
**componentWillReceiveProps**(组件快要接收到属性时触发)——父组件修改属性触发,可以修改新属性、修改状态。
在修改发生之前出发。在属性真正比传送到组件之前,对其进行处理。
**shouldComponentUpdate**(组件接收到新状态时,是否需要更新,返回false,React就不会更新,可以提高性能)
**componentWillUpdate**(组件即将更新到页面)——不能修改属性和状态,会导致死循环
**render**——只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。
**componentDidUpdate**(在组件更新到页面之后调用)——可以修改DOM
~~~
<body>
<div id = "example"></div>
<div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var MyComponent = React.createClass({
getDefaultProps: function(){
console.log("获取实例的默认属性");
return{name: "Yvette"};
},
getInitialState: function () {
console.log("获取实例的初始状态");
return{will:true};
},
componentWillMount: function () {
console.log("组件即将被渲染到页面");
},
handleClick: function(event){
this.setState({will: !this.state.will});
},
componentDidMount: function(){
console.log("组件被渲染到页面之后");
$(this.refs.example).append("啦啦啦");
},
render: function(){
console.log("render")
return(
<div>
<p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
</div>
);
},
componentWillReceiveProps: function(){
console.log("组件快要接收到属性");
},
shouldComponentUpdate: function(){
console.log("是否需要更新");
return false;
},
componentWillUpdate: function(){
console.log("组件即将被更新");
},
componentDidUpdate: function(){
console.log("组件更新被渲染到页面");
}
});
ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>
~~~
运行结果如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570604008875d.jpg)
从运行结果可以看出:
**1、在运行过程中,组件的状态发生改变时,首先进入shouldComponentUpdate函数,即组件是否需要更新,如果返回false,表示无需更新,直接返回。**
~~~
<body>
<div id = "example"></div>
<div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var MyComponent = React.createClass({
getDefaultProps: function(){
console.log("获取实例的默认属性");
return{name: "Yvette"};
},
getInitialState: function () {
console.log("获取实例的初始状态");
return{will:true};
},
componentWillMount: function () {
console.log("组件即将被渲染到页面");
},
handleClick: function(event){
this.setState({will: !this.state.will});
},
componentDidMount: function(){
console.log("组件被渲染到页面之后");
//$(this.refs.example).append("啦啦啦");
},
render: function(){
console.log("render")
return(
<div>
<p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
<span ref = "more">啦啦啦</span>
</div>
);
},
componentWillReceiveProps: function(){
console.log("组件快要接收到属性");
},
shouldComponentUpdate: function(){
console.log("是否需要更新");
return true;
},
componentWillUpdate: function(){
console.log("组件即将被更新");
$(this.refs.example).css({"background": "#ccc","line-height":"30px"});
//this.setState({will: !this.state.will});//导致一个死循环
},
componentDidUpdate: function(){
console.log("组件更新被渲染到页面");
if(this.state.will){
$(this.refs.more).html("啦啦啦");
}
else{
$(this.refs.more).html("郁闷");
}
}
});
ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570604009b2f7.jpg)
从运行结果可以看出钩子函数的触发顺序:
1、shouldComponentUpdate,必须返回true或false,如果返回false,直接返回,不会再触发后面的钩子函数。
2、componentWillUpdate和componentDidUpdate中都可以操作DOM元素,因为当前在运行过程中,组件已经被渲染到了页面。但是最后是在componentDidUpdate中进行修改。
**销毁中阶段能够使用的钩子函数(按照触发顺序):**
**componentWillUnmount**(在销毁操作执行之前触发)——在组件真正被销毁前调用,在删除组件之前进行清理操作,如计时器和事件监听器。
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var style = {
color: "red",
border: "1px solid #000"
};
var HelloWorld = React.createClass({
render: function(){
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount: function(){
console.log("I will unmount");
}
});
var HelloUniverse = React.createClass({
getInitialState: function(){
return {name: "Yvette"};
},
handleChange: function (event) {
if(event.target.value == "123"){
React.unmountComponentAtNode(document.querySelector("#example"))
return;
}
this.setState({name: event.target.value});
},
render: function(){
return(
<div>
<HelloWorld name = {this.state.name}></HelloWorld>
<br/>
<input type = "text" onChange = {this.handleChange} />
</div>
);
}
});
ReactDOM.render(<div style = {style}><HelloUniverse></HelloUniverse></div>,document.querySelector("#example"));
</script>
~~~
当输入结果为123时,触发componentWillUnmount钩子函数。
使用React实现类似快递单号查询效果
最后更新于:2022-04-01 11:56:46
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src = "build/jquery-1.11.2.min.js"></script>
<script src = "build/react.js"></script>
<script src = "build/react-dom.js"></script>
<script src = "build/browser.min.js"></script>
<script type="text/babel">
var MyComponent = React.createClass({
handKeyUp: function () {
this.refs.clone.innerHTML = this.refs.target.value;
},
render: function () {
return (<div>
<div ref = "clone" style = {{height:40+'px',fontSize:28+'px'}}></div>
<input type = "text" ref = "target" onKeyUp = {this.handKeyUp}></input>
</div>);
}
});
ReactDOM.render(<MyComponent></MyComponent>,document.querySelector("#example"));
</script>
~~~
实现效果如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_5706040061a49.jpg)
CSS美化略过,因为主要是学习React使用。
另一种更为简便的写法如下,充分利用react组件的state:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.min.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var Input = React.createClass({
getInitialState: function(){
return {value: "Hello"};
},
handleChange: function (event) {
this.setState({value: event.target.value});
},
render: function(){
var value = this.state.value;
return (
<div>
<p>{value}</p>
<input type = "text" value = {value} onChange = {this.handleChange} />
</div>
);
}
});
ReactDOM.render(
<Input />,
document.querySelector("#example")
)
</script>
~~~
React组件生命周期
最后更新于:2022-04-01 11:56:43
### 什么是生命周期?
组件本子上是状态机,输入确定,输出一定确定。
状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出响应
可以用事件的思路来理解状态。组件可以处于不同的状态中。
初始化阶段————运行中阶段————销毁阶段
初始化阶段能够使用的钩子函数(按照触发顺序):
getDefaultProps(获取实例的默认属性)————只有第一次实例的时候调用
getInitialState(获取实例的初始状态)
componentWillMount(组件即将被渲染到页面)
render(组件在render中生成虚拟的DOM节点,即JSX,最后由React生成真实的DOM节点)
componentDidMount(组件被渲染到页面之后)
运行中阶段能够使用的钩子函数(按照触发顺序):
componentWillReceiveProps(组件快要接收到属性时触发)
shouldComponentUpdate(组件接收到新状态时,是否需要更新,返回false,React就不会更新,可以提高性能)
componentWillUpdate()
render
componentDidUpdate(在组件被渲染到页面之后调用)
销毁中阶段能够使用的钩子函数(按照触发顺序):
componentWillUnmount(在销毁操作执行之前触发)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var HelloMessage = React.createClass({
getDefaultProps: function () {
},
getInitialState: function(){
return {liked: false}
},
componentWillMount: function(){
console.log("Component will mount");
},
render: function(){
return <p ref = "one">Hello, {
(function(obj){
if(obj.props.name){
return obj.props.name;
}else{
return "Message"
}
})(this)}</p>
},
compontentDidMount: function(){}
});
ReactDOM.render(<HelloMessage></HelloMessage>, document.querySelector("#example"));
</script>
~~~
### 初始化阶段介绍
getDefaultProps——只调用一次,实例之间共享引用(属性)
即使没有生成实例,也会调用,在createClass时,就会被调用
getInitialState——初始化每个实例特有的状态
必须返回一个Object或者是Null
componentWillMount——render之前最后一次修改状态的机会
render——只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。
如果render需要修改状态和DOM输出,那么render就不能在服务端使用。并且,如果在render中修改状态和DOM输出,会使得代码逻辑变得复杂。所以,要尽可能避免这样做。
componentDidMount——成功render并渲染完成真实DOM之后触发,可以修改DOM
操作真正的DOM节点:this.refs.XXX
~~~
var Zoo = React.createClass({
render: function() {
return <div>Giraffe name: <input ref="giraffe" /></div>;
},
showName: function() {
// 之前:
var input = this.refs.giraffe.getDOMNode();
// v0.14 版:
var input = this.refs.giraffe;
alert(input.value);
}
});
~~~
需要注意的是,如果你给自定义的 React 组件(除了 DOM 自带的标签,如 div、p 等)添加 refs,表现和行为与之前一致。
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src = "build/react.js"></script>
<script src = "build/react-dom.js"></script>
<script src = "build/browser.min.js"></script>
<script type = "text/babel">
var count = 0;
var HelloMessage = React.createClass({
getDefaultProps: function () {
return {name: "Yvette"};
},
getInitialState: function(){
return {myCount: count++,
ready: false}
},
componentWillMount: function(){
this.setState({ready: true})
},
render: function(){
return <p ref = "one">Hello, {this.props.name ? this.props.name : "Message"} <br/>
{+ this.state.ready} {this.state.myCount}</p>
},
componentDidMount: function(){
$(this.refs.one).append("<span>future</span>");
}
});
ReactDOM.render(<div><HelloMessage></HelloMessage><HelloMessage></HelloMessage></div>, document.querySelector("#example"));
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_5706040049a94.jpg)
### 运行中阶段介绍
componentWillReceiveProps:父组件修改属性触发,可以修改新属性、修改状态。
在修改发生之前出发。在属性真正比传送到组件之前,对其进行处理。
shouldComponentUpdate:返回false会阻止render调用,后面的函数都不会执行。
componentWillUpdate:不能修改属性和状态
render:只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。
componentDidUpdate:可以修改DOM
### 销毁阶段介绍
componentWillUnmount:在组件真正被销毁前调用,在删除组件之前进行清理操作,如计时器和事件监听器。
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var style = {
color: "red",
border: "1px solid #000"
};
var HelloWorld = React.createClass({
render: function(){
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount: function(){
console.log("I will unmount");
}
});
var HelloUniverse = React.createClass({
getInitialState: function(){
return {name: "Yvette"};
},
handleChange: function (event) {
if(event.target.value == "123"){
React.unmountComponentAtNode(document.querySelector("#example"))
return;
}
this.setState({name: event.target.value});
},
render: function(){
return(
<div>
<HelloWorld name = {this.state.name}></HelloWorld>
<br/>
<input type = "text" onChange = {this.handleChange} />
</div>
);
}
});
ReactDOM.render(<div style = {style}><HelloUniverse></HelloUniverse></div>,document.querySelector("#example"));
</script>
~~~
在input中输入123,可以触发componentWillUnmount事件。
使用React.unmountComponentAtNode(para);//传入的参数必须是装载时的节点,即ReactDOM.render()的第二个参数。
除了上面的方法外,还可以在render中写判断,如下:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
</head>
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var style = {
color: "red",
border: "1px solid #000"
};
var HelloWorld = React.createClass({
render: function(){
return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
},
componentWillUnmount: function(){
console.log("I will unmount");
}
});
var HelloUniverse = React.createClass({
getInitialState: function(){
return {name: "Yvette"};
},
handleChange: function (event) {
this.setState({name: event.target.value});
},
render: function(){
if(this.state.name == "123"){
return <div>123</div>
}
return(
<div>
<HelloWorld name = {this.state.name}></HelloWorld>
<br/>
<input type = "text" onChange = {this.handleChange} />
</div>
);
}
});
ReactDOM.render(<div style = {style}><HelloUniverse></HelloUniverse></div>,document.querySelector("#example"));
</script>
~~~
reactJS入门
最后更新于:2022-04-01 11:56:41
在使用React 0.14版本时,需要引入react.js/react-dom.js/browser.min.js
### ReactDOM.render
ReactDOM.render()将JSX转换成HTML,并且将其插入特定的DOM节点。在0.14版本之前,使用的是React.render()方法,目前还支持,但是React不推荐使用。
~~~
<body>
<div id = "container"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.querySelector('#container')
);
</script>
~~~
上面代码一共用了三个库: react.js 、react-dom.js 和 browser.js ,它们必须首先加载。最后一个 `<script>` 标签的 type 属性为 text/babel 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type=”text/babel” 。
react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成,在V0.14版本之前,react使用 JSTransform.js 解析 `<script type="text/jsx">`
react不依赖于jquery,我们可以使用jquery,但是render里面的第二个参数必须使用Javascript原生的方法,不能用jquery来选取DOM节点。
### JSX语法
HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。
JSX 的基本语法规则:遇到 HTML 标签(以<开头),就用 HTML 规则解析;遇到代码块(以{开头),就用 JavaScript 规则解析。
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src = "build/react.js"></script>
<script src = "build/react-dom.js"></script>
<script src = "build/browser.min.js"></script>
<script type = "text/babel">
var names = ["Alice", "Emily", "Kate"];
ReactDOM.render(
<div>
{
names.map(function(name){
return <div>Hello, {name}</div>
})
}
</div>,
document.querySelector("#example")
)
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ffb0b55.jpg)
从生成的Html代码,我们可以看出,每一个Html标签都有一个data-reactid属性。
JSX允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var arry = [
<h1>Hello world</h1>,
<h2>React is awesome</h2>
];
ReactDOM.render(
<div>{arry}</div>,
document.querySelector("#example")
);
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ffc286f.jpg)
### 组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类.
~~~
<body>
<div id = "example"></div>
<div id = "container"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var HelloMessage = React.createClass({
render: function(){
return <h1>Hello{this.props.name}</h1>;
}
});
ReactDOM.render(
<HelloMessage name = "John" />,
document.querySelector("#example")
);
ReactDOM.render(
<HelloMessage name = "Yvette" />,
document.querySelector("#container")
);
</script>
~~~
变量 HelloMessage就是一个组件类。模板插入 时,会自动生成 HelloMessage的一个实例,每个组件都有render方法,这是组件最基本的方法。此外,还必须注意的是,组件类的首字母必须大写,否则React会将其视为普通的html标签,但是,html中又无此标签,就会报错。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ffd933f.jpg)
组件类只能包含一个顶层标签,否则也会报错。
~~~
<body>
<div id = "example"></div>
</body>
</html>
<script src = "build/react.js"></script>
<script src = "build/react-dom.js"></script>
<script src = "build/browser.min.js"></script>
<script type="text/babel">
var HelloMessage = React.createClass({
render: function(){
return <h1>Hello {this.props.name}
</h1><p>Are you happy?</p>
}
});
ReactDOM.render(
<HelloMessage name = "Yvette"/>,
document.querySelector("#example")
);
</script>
~~~
上面代码会报错,因为HelloMessage组件包含了两个顶层标签:h1和p
组件的用法与原生的 HTML 标签完全一致,可以任意加入属性,比如 ,就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,比如 name 属性就可以通过 this.props.name 读取。
添加组件属性,有一个地方需要注意,就是 class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。
### this.props.children
this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点
~~~
<script type="text/babel">
var NodeList = React.createClass({
render: function(){
return(
<ol>
{
React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})
}
</ol>
);
}
});
ReactDOM.render(
<NodeList>
<span>Dream</span>
<span>Future</span>
</NodeList>,
document.querySelector("#example")
);
</script>
~~~
NoteList 组件有两个 span 子节点,它们都可以通过 this.props.children 读取,运行结果如下。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ffe9cd6.jpg)
需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined;如果有一个子节点,数据类型是 object;如果有多个子节点,数据类型就是 array。所以,处理 this.props.children 的时候要小心。
React 提供一个工具方法React.Children来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。
### PropTypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。
组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求,如果引入的是react.min.js,那么此属性没有作用,控制台不会报错。当前版本是V0.14.8
~~~
<script src = "build/react.js"></script>
<script src = "build/react-dom.js"></script>
<script src = "build/browser.min.js"></script>
<script type="text/babel">
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
var data = 123;
ReactDOM.render(
<MyTitle title={data} />,
document.body
);
</script>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_57060400073d7.jpg)
getDefaultProps方法可以用来设置组件属性的默认值
~~~
<script type="text/babel">
var MyTitle = React.createClass({
getDefaultProps: function(){
return{
title: "Hello World"
};
},
render: function(){
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle />,
document.querySelector("#example")
)
</script>
~~~
### 获取真实的DOM节点
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
附上DOM diff的流程图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570604001c768.jpg)
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到ref属性。
~~~
<script type="text/babel">
var MyComponent = React.createClass({
handleClick: function(){
this.refs.myTextInput.focus();
},
render: function(){
return (
<div>
<input type = "text" ref = "myTextInput" />
<input type = "button" value = "Focus the text input" onClick = {this.handleClick} />
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
document.querySelector("#example")
)
</script>
~~~
组件 MyComponent的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click事件之后,才会读取 this.refs.[refName] 属性。
React 组件支持很多事件,除了 Click 事件以外,还有 KeyDown 、Copy、Scroll 等。
### this.state
React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。
~~~
<script type="text/babel">
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function (event) {
this.setState({liked: !this.state.liked});
},
render: function(){
var text = this.state.liked ? "like" : "haven\'t like";
return (
<p onClick = {this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.querySelector("#example")
);
</script>
~~~
上面代码是一个 LikeButton组件,它的 getInitialState方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。
由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。
### 表单
用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取。
~~~
<script type="text/babel">
var Input = React.createClass({
getInitialState: function(){
return {value: "Hello"};
},
handleChange: function (event) {
this.setState({value: event.target.value});
},
render: function(){
var value = this.state.value;
return (
<div>
<input type = "text" value = {value} onChange = {this.handleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(
<Input />,
document.querySelector("#example")
)
</script>
~~~
文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况
如何在Html中引入外部页面
最后更新于:2022-04-01 11:56:39
通常一个网站的head,foot,rightBar(右侧的条目)都是相同的,这部分内容可以通过引入的方式,否则一旦需要修改,就需要修改十个,二十个,乃至更多的页面,是一项既繁琐但又毫无意义的工作。借助于PHP或者JSP,使用include能够轻松解决此问题,但是如果脱离后端语言,从前端的角度,能不能解决这个问题呢?
### 1、借助于iframe
首先,最容易想到的应该是使用iframe,虽然html5废除了frame,但是依旧保留了iframe,我们仍可以继续使用,iframe有一个frameboder属性,设置属性值为0或者为no,去除iframe的边框。然后将scrolling设为no。这是完全可行的,不过记得要在服务器环境下运行。
~~~
var frame = document.getElementsByTageName("iframe")[0];
frame.contentWindow.document.XXX方法,
如frame.contentWindow.document.querySelector("#btn");//获取iframe中Id为btn的节点.
~~~
因为此前没有使用iframe来引入头部的经验,考虑到头部通常除了跳转之外,另一个作用应该是定位,在页面较长时,通过点击,准确定位到某处。页面的跳转,使用iframe引入并无影响,那么锚点呢?这个需要试一试才知道。
在此,再补充一点关于锚点的知识:
锚点可以跳转到当前页面的相应位置,还可以跳转到其它页面的相应位置。
实现锚点有两种方式,一种是a标签+name属性,还有一种是使用标签的Id属性。
具体如下:
a.使用a标签+name属性的方式
~~~
<a href = "#detail">详情</a>
<a name = "detail"></a>
~~~
点击”详情”,跳转到`<a name = "detail">`的位置.
b.使用标签的id属性
~~~
<a href = "#detail">详情</a>
<div id = "detail"></div>
~~~
点击”详情”,跳转到`<div id = "detail">`的位置.
使用a+name的方式经常会出现锚点失效的情况,因此推荐使用id来绑定锚点。
言归正传,引入iframe之后,我们能否通过点击iframe中的元素来定位的相应的位置呢,这里,我们使用iframe引入head.html,这也是我最初的目的。
因此我们要实现的是:点击iframe的a标签,定位到主Html相应的位置,通过实现发现,单纯通过html是无法实现的,但是借助于JS则可以做到。
~~~
<!doctype html>
<html lang="en">
<head>
<!--网站编码格式,UTF-8 国际编码,GBK或 gb2312 中文编码-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="Yvette Lau">
<title>Document</title>
<!--css js 文件的引入-->
<style>
#leftFrame{display:block;}
</style>
</head>
<body>
<div><img src = "img/photo1.jpg" width="500px"/></div>
<iframe src="test1.html" height= "100px" name="leftFrame" scrolling="No" noresize="noresize" id="leftFrame"></iframe>
<div><img src = "img/photo2.jpg" width="500px"/></div>
<div><img src = "img/photo3.jpg" width="500px" /></div>
<p id = "buttom">detail</p>
</body>
</html>
<script>
window.onload = function(){
var iframe = document.querySelector("#leftFrame");
var bot = iframe.contentWindow.document.querySelector("#bot");
var top = iframe.contentWindow.document.querySelector("#top");
bot.onclick = function(){
document.body.scrollTop = document.body.offsetHeight;
};
top.onclick = function(){
document.body.scrollTop = 0;
};
};
</script>
~~~
iframe中有id为bot和top的元素。通过JS的方式实现定位。
在主页面中,通过iframe.contentWindow能够以HTML对象来返回iframe中的文档,可以通过所以标准的DOM方法来处理被返回的对象。
在iframe页面中,通过parent定位到父html,可以通过top定位到顶层的html.
同级iframe之间调用,需要先定位到父html,再定位到iframe.
补充点关于锚点的知识,其关键作用的就是连接地址后面加的#detail(detail仅是泛指).如果当前的url为localhost:8080/index.html.那么锚点之后,url应为localhost:8080/index.html#detail
URL地址末尾带有”#”标识符,表示需要跳转到对应的位置。#idName,浏览器会在页面中找到符合”#idName”特点的标签。如果URL中”#”后面跟随的字符在文中找不到,如果是当前页面,那么不跳转,如果是从其它页面跳转过来,则显示页面顶部。
回到页面顶部,除了可以通过JS设置body的scrollTop(0返回到顶部,设置为body的高度,跳转到顶部),另一种方法就是`<a href = "#">回到顶部</a>`
### 2、借助于ajax(jquery的load方法)
另外还有一种方法,是借助于jQuery的load方法载入页面。
load(url, data, callback);url是待装入HTML网页网址;data:发送至服务器的key/value;callback:载入成功时回调函数。
~~~
$(function(){
$("selector1").load("page1.html");
$("selector2").load("page2.html");
$("selector3").load("page3.html");
});
~~~
通过js追加进来的DOM结构,对SEO(搜索引擎优化)有影响,类似百度蜘蛛是无法抓取的!一般情况下不到万不得已的时候,不推荐使用。page1.html/page2.html/page3.html写需要的Html片段即可,因为是load进来的,也就是异步加载,在需要获取page1.html等页面的元素时,可以结合setTimeout使用,确保页面被加载进来。
### 3、使用HTML imports
HTML imports提供了一种在一个HTML文档中包含和重用另一个HTML文档的方法。目前谷歌已经全面支持HTML imports,Opera35版本之后支持,但是FF依旧不支持。(在谷歌的地址栏输入:chrome://flags,启动或禁止一些功能)
尽管目前HTML imports的兼容不是很好,但是我们还是有必要了解其使用方法,W3C已经发布了HTML imports的标准草案,相信后期应该还是会用得比较普遍的。使用HTML imports
~~~
<!doctype html>
<html lang="en">
<head>
<!--网站编码格式,UTF-8 国际编码,GBK或 gb2312 中文编码-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="Yvette Lau">
<title>Document</title>
<link rel = "import" href = "test1.html"/>
</head>
<body>
<div id = "content"></div>
</body>
</html>
<script>
var post = document.querySelector("link[rel = 'import']").import;
var con = post.querySelector("div");
document.querySelector("#content").appendChild(con.cloneNode(true));
var clone = document.importNode(con,true)
document.querySelector("#content").appendChild(clone)
</script>
~~~
给出了两种将import进来的html中我们需要的部分插入到当前html.
最后简单介绍document.querySelector和document.querySelectorAll,这两个方法是HTML5在Web API中新引入的方法,大大简化了在原生Javascript代码中选取元素。
document.querySelector和document.querySelectorAll都是接收一个字符串作为参数,这个参数需要符合CSS选择语法,即:标签、类选择器、ID选择器,属性选择器(E[type=”XX”]),结构选择器(:nth-child(n))等。不支持伪类选择器。
document.importNode(node,deep)方法把一个节点从另一个文档复制到该文档以便应用,第二个值为true,那么将该节点的所有子孙节点也复制过来。
node.cloneNode(deep):对已有的节点进行克隆,deep值为true,表示克隆其子孙节点。如果deep为false,则只克隆该节点自身。
除了以上方法外,目前更为主流的一种方式是使用组件化开发。每一部分作为一个组件。
CSS自动换行、强制不换行、强制断行、超出显示省略号
最后更新于:2022-04-01 11:56:36
P标签是默认是自动换行的,因此设置好宽度之后,能够较好的实现效果,但是最近的项目中发现,使用ajax加载数据之后,p标签内的内容没有换行,导致布局错乱,于是尝试着使用换行样式,虽然解决了问题,但是并没有发现本质原因,本质在于,我当时获取的数据是一长串的数字,浏览器应该是对数字和英文单词处理方式相近,不会截断。
先给出各种方式,再具体介绍每一个属性。
强制不换行
p { white-space:nowrap; }
自动换行
p { word-wrap:break-word; }
强制英文单词断行
p { word-break:break-all; }
注意:设置强制将英文单词断行,需要将行内元素设置为块级元素。
超出显示省略号
p{text-overflow:ellipsis;overflow:hidden;}
**white-space: normal|pre|nowrap|pre-wrap|pre-line|inherit;**
white-space 属性设置如何处理元素内的空白
normal 默认。空白会被浏览器忽略。
pre 空白会被浏览器保留。其行为方式类似 HTML 中的 pre 标签。
nowrap 文本不会换行,文本会在在同一行上继续,直到遇到 br 标签为止。
pre-wrap 保留空白符序列,但是正常地进行换行。
pre-line 合并空白符序列,但是保留换行符。
inherit 规定应该从父元素继承 white-space 属性的值。
**word-wrap: normal|break-word;**
word-wrap 属性用来标明是否允许浏览器在单词内进行断句,这是为了防止当一个字符串太长而找不到它的自然断句点时产生溢出现象。
normal: 只在允许的断字点换行(浏览器保持默认处理)
break-word:在长单词或URL地址内部进行换行
word-break: normal|break-all|keep-all;
**word-break 属性用来标明怎么样进行单词内的断句。**
normal:使用浏览器默认的换行规则。
break-all:允许再单词内换行
keep-all:只能在半角空格或连字符处换行
举例看起区别:
~~~
<!doctype html>
<html lang="en">
<head>
<!--网站编码格式,UTF-8 国际编码,GBK或 gb2312 中文编码-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="Yvette Lau">
<title>Document</title>
<!--css js 文件的引入-->
<style>
.word{background:#E4FFE9;width:250px;margin:50px auto;padding:20px;font-family:"microsoft yahei";}
/* 强制不换行 */
.nowrap{white-space:nowrap;}
/* 允许单词内断句,首先会尝试挪到下一行,看看下一行的宽度够不够,
不够的话就进行单词内的断句 */
.breakword{word-wrap: break-word;}
/* 断句时,不会把长单词挪到下一行,而是直接进行单词内的断句 */
.breakAll{word-break:break-all;}
/* 超出部分显示省略号 */
.ellipsis{text-overflow:ellipsis;overflow:hidden;}
</style>
</head>
<body>
<div class = "word">
<p class = "nowrap">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfs</p>
<p class = "breakword">wordwrap:break-word;absavhsafhuafdfbjhfvsalguvfaihui</p>
<p class = "breakAll">wordwrap:break-word;absavhsafhuafdfbjhfvsalguvfaihuivf</p>
<p class = "normal">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfsa</p>
<p class = "ellipsis">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfsab</p>
</div>
</body>
</html>
~~~
效果如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff932d6.jpg)
前端在html页面之间传递参数的方法
最后更新于:2022-04-01 11:56:34
项目中经常会出现的一种情况,有一个列表,譬如是案例列表,点击列表中的某一项,跳转至详情页面。详情是根据所点击的某条记录生成的,因为案例和具体的详情页面,都是用户后期自行添加的,我们开始编写时,不可能穷尽。因此跳转页面时,我们需要传递一个参数过去,这样我们才能通过这个参数进行数据请求,然后根据后台返回的数据来生成页面。因此,通过a标签跳转的方式,肯定是行不通的。
我们经常写form表单,提交时,可以传递参数,如果使用表单,并将其隐藏起来,应该可以达到效果。
除此以外,window.location.href和window.open也可以达到效果。
### 1、通过form表单传递参数
~~~
<html lang="en">
<head>
<!--网站编码格式,UTF-8 国际编码,GBK或 gb2312 中文编码-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="Yvette Lau">
<title>Document</title>
<!--css js 文件的引入-->
<!-- <link rel="shortcut icon" href="images/favicon.ico"> -->
<link rel="stylesheet" href=""/>
<script type = "text/javascript" src = "jquery-1.11.2.min.js"></script>
</head>
<body>
<form name = "frm" method = "get" action = "receive.html" onsubmit = "return foo()" style = "position:relative;">
<input type="hidden" name="hid" value = "" index = "lemon">
<img class = "more" src = "main_jpg10.png" />
<input type = "submit" style = "position:absolute;left:10px;top:0px;width:120px;height:40px;opacity:0;cursor:pointer;"/>
</form>
<form name = "frm" method = "get" action = "receive.html" onsubmit = "return foo()" style = "position:relative;">
<input type="hidden" name="hid" value = "" index = "aaa">
<img class = "more" src = "main_jpg10.png" />
<input type = "submit" style = "position:absolute;left:10px;top:0px;width:120px;height:40px;opacity:0;cursor:pointer;"/>
</form>
<form name = "frm" method = "get" action = "receive.html" onsubmit = "return foo()" style = "position:relative;">
<input type="hidden" name="hid" value = "" index = "bbb">
<img class = "more" src = "main_jpg10.png" />
<input type = "submit" style = "position:absolute;left:10px;top:0px;width:120px;height:40px;opacity:0;cursor:pointer;"/>
</form>
</body>
</html>
<script>
function foo(){
var frm = window.event.srcElement;
frm.hid.value = $(frm.hid).attr("index");
return true;
}
</script>
~~~
点击图片时,跳转至receive.html页面。页面的url变成:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff70378.jpg)
我们想要传的字符串已经传递了过来。
然后再对当前的url进行字符串分割
window.location.href.split(“=”)[1]//得到lemon
我们拿到需要传来的参数之后,就可以根据这个进行下一步的处理了。
除了上述通过字符串分割来获取url传递的参数外,我们还可以通过正则匹配和window.location.search方法来获取。
### 2、通过window.location.href
譬如我们点击某个列表,需要传递一个字符串到detail.html页面,然后detail.html页面根据传来的值,通过ajax交互数据,加载页面的内容。
var index = "lemon"; var url = "receive.html?index="+index; $("#more").click(function(){ window.location.href = url; });
当前页面会被替换成recieve.html的页面,页面的url变为:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff7fda6.jpg)
然后我们再用上面的方法提取自己需要的参数
### 3、通过window.location.open
如果是希望打开一个新页面,而不是改变当前的页面,那么window.location.href就不适用了,此时,我们需要借助于window.location.open()来实现
简单介绍有一下window.open()函数,window.open()有三个参数,第一个参数是要打开的页面的url,第二个参数是窗口目标,第三个参数是一个特定字符串以及一个表示新页面是否取代浏览器历史集中当前加载页面的布尔值,通过只需要传递第一个参数。第二个参数还可以是”_blank”,”_self”,”_parent”,”_top”这样的特殊窗口名称,”_blank”打开新窗口,”_self”实现的效果同window.location.href.
继续上面的例子:
~~~
<script>
var index = "lemon";
var url = "receive.html?index="+index;
$("#more").click(function(){
window.open(url)
});
</script>
~~~
这样在点击的时候,就会打开一个新页面,页面的url地址与上面相同。
由于浏览器的安全限制,有些浏览器在弹出窗口配置方面增加限制,大多数浏览器都内置有弹出窗口的屏蔽程序,因此,弹出窗口有可能被屏蔽,在弹出窗口被屏蔽时,需要考虑两种可能性,一种是浏览器内置的屏蔽程序阻止弹出窗口,那么 window.open()很可能返回Null,此时,只要监测这个返回的值就可以确定弹出窗口是否被屏蔽。
~~~
var newWin = window.open(url);
if(newWin == null){
alert("弹窗被阻止");
}
~~~
另一种是浏览器扩展或其他程序阻止的弹出窗口,那么window.open()通常会抛出一个错误,因此,要像准确的检测弹出窗口是否被屏蔽,必须在检测返回值的同时,将window.open()封装在try-catch块中,上面的例子中可以写成如下形式:
~~~
<script>
var blocked = false;
try{
var index = "lemon";
var url = "receive.html?index="+index;
$("#more").click(function(){
var newWin = window.open(url);
if(newWin == null){
blocked = true;
}
});
} catch(ex){
block = true;
}
if(blocked){
alert("弹出窗口被阻止");
}
</script>
~~~
利用@font-face实现个性化字体
最后更新于:2022-04-01 11:56:32
字体转换网站:[http://www.fontsquirrel.com/tools/webfont-ge](http://www.fontsquirrel.com/tools/webfont-ge)
可以将字体转换为网页兼容格式字体eot,otf,svg,wotf
新项目中需要使用:造字工坊悦黑字体,该字体并非主流操作系统的内置字体,使用font-family属性无法实现。但是可以通过CSS3的@font-face实现。
1、使用CSS的@font-face首先需要获取要使用的字体的三种文件格式,确保能在主流浏览器中正常显示该字体。
.ttf或.otf(适用于 Firefox3.5、Safari、Opera)
.eot(适用于IE4+)
.svg(适用于Chrome、Iphone)
声明一个名为missYuan的字体.
在网上下载好字体后,通常是otf格式,然后通过字体转换网站进行格式转换
2、在样式表中声明该字体。
~~~
@font-face {
font-family: ‘rtws_yuegothic_triallight’;
src: url(‘missyuan-webfont.eot’);
src: url(‘missyuan-webfont.eot?#iefix’) format(‘embedded-opentype’),
url(‘missyuan-webfont.woff2’) format(‘woff2’),
url(‘missyuan-webfont.woff’) format(‘woff’),
url(‘missyuan-webfont.ttf’) format(‘truetype’),
url(‘missyuan-webfont.svg#rtws_yuegothic_triallight’) format(‘svg’);
font-weight: normal;
font-style: normal;
}
~~~
3、在需要的地方使用该字体
如p{font-size:24px;font-weight:bold;}
JS模块化开发(requireJS)
最后更新于:2022-04-01 11:56:30
**使用模块化开发的好处:**
**通过 exports 暴露接口**。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。
**通过 require 引入依赖。**这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js/ Require.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣
实现JS模块化开发,目前有两个规范,一个是AMD规范,一个是CMD规范。
RequireJS遵循的是AMD规范。AMD推崇依赖前置。
SeaJS遵循的CMD规范。CMD推崇依赖就近(按需加载)
AMD:API根据使用范围有区别,但使用同一个api接口
CMD:每个API的职责单一
**AMD规范的模块风格**
1、 定义模块用module变量,它有一个方法declare
2、 declare接受一个函数类型的参数,如称为factory
3、 factory有三个参数分别为require、exports、module,factory使用返回值和exports导出API. factory如果是对象类型,则将该对象作为模块输出
~~~
define(function(require, exports, module) {
var base = require('base');
exports.show = function() {
// todo with modulebase
}
});
~~~
使用require获取依赖模块,使用exports导出API。
除了require之外,AMD还保留了一个关键字require。require作为规范保留的全局标识符,可以实现为modile loader.
AMD的库有RequireJS、curl、Dojo、Nodules等
requireJS和seaJS应该是各有千秋,但是因为我之前的一个项目中使用到了requireJS,所以我选择对requireJS进行深入研究。
**requireJs**
(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。
RequireJS用法介绍。
requirejs官网是: [http://requirejs.org/](http://requirejs.org/)
官方下载地址:[http://requirejs.org/docs/release/2.1.20/minified/require.js](http://requirejs.org/docs/release/2.1.20/minified/require.js)
先下载require.js.
require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。
require.js的加载
1、在页面底部加载。
2、`<script src="js/require.js" defer async="true" ></script>`
async属性表面这个文件需要异步加载,避免网页失去响应,IE不支持async,需要使用defer属性。
加载require.js以后,下一步就要加载我们自己的代码了。
~~~
<script src="js/require.js" data-main="js/main"></script>
~~~
data-main属性的作用是,指定网页程序的主模块。
**main.js文件**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe0fd23.jpg)
引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行.
require的项目中,所有需要引入的文件都不要写.js的后缀名,因为requirejs会自动添加.js的后缀名。
**define 模块**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe1f85d.jpg)
将该模块命名为math.js保存。
define 定义模块方法只能用在独立的js文件中,不能在页面中直接使用。
否则会报 Mismatched anonymous define() module 错误。
**没有依赖**
如果定义的模块不依赖其他模块,则可以:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe300c0.jpg)
AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。
当写一个没有任何依赖的模块,并且只是返回一个对象包含一些功能函数
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe3fd9f.jpg)
**循环依赖**
在一些情况中,我们可能需要模块moduleA和moduleA中的函数需要依赖一些应用。这就是循环依赖。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe54152.jpg)
**math.js引入模块方法**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe681d2.jpg)
AMD规范定义的require()函数:
~~~
require(['moduleA', 'moduleB', 'moduleC'],
function (moduleA, moduleB, moduleC){
// some code here
});
~~~
require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是[‘moduleA’, ‘moduleB’, ‘moduleC’],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
假定主模块依赖jquery、underscore和backbone这三个模块,main.js就可以这样写:
~~~
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
// some code here
});
~~~
require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。
**模块的加载**
主模块的依赖模块是[‘jquery’, ‘underscore’, ‘backbone’]。默认情况下,require.js假定这三个模块与main.js在同一个目录,文件名分别为 jquery.js,underscore.js和backbone.js,然后自动加载。
使用require.config()方法,我们可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe7a276.jpg)
上面的代码给出了三个模块的文件名,路径默认与main.js在同一个目录(js子目录)。如果这些模块在其他目录,比如js/lib目录,则有两种写法。一种是逐一指定路径。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe8ae12.jpg)
另一种则是直接改变基目录(baseUrl)。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fe9a52c.jpg)
如果某个模块在另一台主机上,也可以直接指定它的网址,比如:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603feaac2f.jpg)
require.js要求,每个模块是一个单独的js文件。这样的话,如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度。因此,require.js提供了一个优化工具,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数。
在代码中require一个文件多次,不会导致浏览器反复加载,即使反复require它,它也只加载一次。
CDN回退,当CDN加载不正确时,回退到本地相应的库2,通过require.config实现。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fecec18.jpg)
**AMD模块的写法**
require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。
具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。
//math.js
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fedf410.jpg)
加载方法如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603feeeca9.jpg)
如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff0c980.jpg)
当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。
**加载非规范的模块**
理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合.require.js能够加载非规范的模块,方法是,在用require()加载之前,要先用require.config()方法定义它们的一些特征。
举例来说,underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载它们的话,必须先定义它们的特征。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff1c8c4.jpg)
require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff308a5.jpg)
**得到模块的地址**
~~~
var path = require.toUrl("./style.css");
~~~
**JSONP**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff3f459.jpg)
**require.js插件**
require.js还提供一系列插件,实现一些特定的功能。
domready插件,可以让回调函数在页面DOM结构加载完成后再运行。
text和image插件,则是允许require.js加载文本和图片文件
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603ff50a25.jpg)
类似的插件还有json和mdown,用于加载json文件和markdown文件。
**r.js压缩**
Require.js 提供一个脚本 r.js ,可以将所有使用到的模块压缩成一个脚本文件,r.js 可以使用node.js 来执行。
在压缩模块前,需要写一个配置文件,说明主模块名,压缩后的文件名,哪些模块不要压缩
没有使用 define 定义的模块都不要压缩,包括 jquery,backbone 等库及其插件
CSS3响应式布局
最后更新于:2022-04-01 11:56:27
### 响应式布局有哪些优点和缺点
**优点:**
面对不同分辨率设备灵活性强
能够快捷解决多设备显示适应问题
**缺点:**
兼容各种设备工作量大,效率低下 代码累赘,会出现隐藏无用的元素,加载时间加长
其实这是一种折衷性质的设计解决方案,多方面因素影响而达不到最佳效果
一定程度上改变了网站原有的布局结构,会出现用户混淆的情况
### 1、Media Query
CSS3中的Media Query(媒介查询)
Media Query是制作响应式布局的一个利器,使用这个工具,我们可以非常方便快捷的制造出各种丰富的实用性强的界面。根据视窗的大小自动调整布局。
**1、通过不同的媒体类型和条件定义样式表规则。**
媒体查询让CSS可以更精确作用于不同的媒体类型和同一媒体的不同条件。媒体查询的大部分媒体特性都接受 min和max用于表达”大于或等于”和”小与或等于”。如:width会有min-width和max-width媒体查询可以被用在CSS中的 @media和@import规则上,也可以被用在HTML和XML中。通过这个标签属性,我们可以很方便的在不同的设备下实现丰富的界面
**2、Media能获得的值**
设备的宽和高: device-width,device-height显示屏幕/触觉设备
渲染窗口的宽和高: width,heigth显示屏幕/触觉设备
设备的手持方向: orientation(portrait|lanscape) 横向/竖向
画面比例: aspect-ratio 浏览器的长宽比
屏幕比例: device-aspect-ratio 设备屏幕的长宽比,如4/3,16/9等。
视觉媒体: color 定义每一组输出设备的彩色原件个数,如果不是彩色设备,则值等于0
分辨率: resolution 定义设备的非暴力,如:96dpi,300dpi
以上仅仅orientation不支持max,min.
**3、可用设备参数名**
all 所有设备
braille 盲文
embossed 盲文打印
handheld 手持设备
print 文档打印或者打印预览模式
projection项目演示(如幻灯片)
screen 彩色电脑屏幕
tty 固定字母间距的网络媒体,如电传打字机
**4、逻辑关键字**
only 限定某种设备类型
and 逻辑与,连接设备名与选择条件、选择条件1与选择条件2
not 排除某种设备(除了什么之外)
, 设备列表
**5、语法结构及用法**
@media 设备名 only (选取条件) not (选取条件) and (设备选取条件), 设备二{sRules}
在link中使用@media:
<link rel = "stylesheet" type = "text/css" media = "only screen and (max-width: 640px),only screen and (max-device-width: 640px)"
href = “home.css”/>
only可以省略,第一个条件是网页的最大宽度是640,第二个条件是设备的最大宽度是640px。
@media (min-device-width:1024px) and (max-width:989px), screen and (max-device-width:480px),(max-device-width:480px) and (orientation:landscape),(min-device-width:480px) and (max-device-width:1024px) and (orientation:portrait) {//code}
电脑屏幕尺寸不小于1024px,并且最大的可见宽度为989px;设备最大宽度为480px,并且横向放置,设备宽度不小于480px,并且小于1024px,竖直放置的设备。
字符间以空格相连,选取条件包含在小括号内,code为设置的样式表,包含在中括号里面。only(限定某种设备,可省略),and(逻辑与),not(排除某种设备)为逻辑关键字,多种设备用逗号分隔.
**6、测试响应式布局**
响应式布局需要在不同的设备上测试,可以使用浏览工具来检验不同尺寸屏幕小的显示效果。帮助你在不同尺寸屏幕下浏览网站效果的工具 - Responsivator [http://responsive.d3corp.com/?d3corp.com](http://responsive.d3corp.com/?d3corp.com)
**7、响应式布局设计**
~~~
/*浏览器的可视区域不小于980px*/
@media screen and (min-width:980px){
.head{width:100%; height:70px; }
.head #logo{position:fixed; top:0px; left:50px;}
.head nav{ width:870px;background:#fff;height:70px; margin:0 auto;}
.head nav a{ width:100px; height:40px; margin:15px 0px; display:inline-block; }
}
/*浏览器的可视区域在640px和980px之间*/
@media screen and (min-width:640px) and (max-width:980px){
.head{width:70px;height:870px;}
.head nav{ width:70px;background:#fff;height:870px;margin-top:20px;}
.head nav a{ width:70px; height:40px; margin:15px 0px; display:inline-block; }
}
/*浏览器的可视区域小于640px*/
@media screen and (max-width:640px){
.head{width:256px; height:256px;position:fixed; bottom:20px; left:20px;}
.head #logo{position:absolute; top:0px; left:0px; right:0; bottom:0; padding:auto; margin:auto;}
.head nav{width:256px; height:256px;background-color:rgba(0,0,0,0.6); border-radius:50%; transform:scale(0.1) rotate(-270deg); opacity:0; transition:all 500ms;margin-top:0px;}
.head nav a{display:block; width:40px;height:40px;border-radius:50%; position:absolute;margin-left:-20px; margin-top:-20px; }
~~~
为了更好的显示效果,往往还要格式化一些CSS属性的初始值,如:
~~~
/* 禁用iPhone中Safari的字号自动调整 */
html {
-webkit-text-size-adjust: none;
}
/* 设置HTML5元素为块 */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
display: block;
}
~~~
### 2、利用meta标签对viewport进行控制
移动设备默认的viewport是layout viewport,也就是那个比屏幕要宽的viewport,但在进行移动设备网站的开发时,我们需要的是ideal viewport。
设置width为decice-width;
~~~
<meta name="viewport" content="width=device-width; initial-scale=1.0">
~~~
content中参数设置:
width – viewport的宽度
height – viewport的高度,这个属性很少使用
initial-scale – 初始的缩放比例
minimum-scale – 允许用户缩放到的最小比例
maximum-scale – 允许用户缩放到的最大比例
user-scalable – 用户是否可以手动缩放 no或者yes
最后对于在IE浏览器中不支持media query的情况,我们可以使用Media Query JavaScript来解决,只需要在页面头部引用css3-mediaqueries.js即可。示例:
IE8及低版本浏览器不支持CSS3 media queries的解决方法
另外关于IE8低版本兼容问题可参考:[http://blog.csdn.net/wuruixn/article/details/8642934](http://blog.csdn.net/wuruixn/article/details/8642934)
JS实现继承的几种方式详述(推荐)
最后更新于:2022-04-01 11:56:25
ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的。
### 原型链
原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的指针。如果:我们让原型对象A等于另一个类型B的实例,那么原型对象A就会有一个指针指向B的原型对象,相应的B的原型对象中保存着指向其构造函数的指针。假如B的原型对象又是另一个类型的实例,那么上述的关系依旧成立,如此层层递进,就构成了实例与原型的链条。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd4b386.jpg)
实例以及构造函数和原型之间的关系图如下所示:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd5de9d.jpg)
person.constructor现在指向的是Parent,这是因为Child.prototype指向了Parent的原型,而Parent原型对象的constructor指向Parent。
当以读取模式访问一个实例属性时,首先会在实例中搜索该属性,如果没有找到该属性,则会继续搜索实例的原型。在通过原型链实现的集成中,搜索过程就会沿着原型链继续向上,直到搜索到原型链的末端。
例如,调用person.getParentValue()方法,1)搜索实例;2)搜索Child.prototype;3)搜索Parent.prototype;找到了getParentValue()方法停止。
**1、默认的原型**
前面的例子中展示的原型链少了一环,所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。因此默认的原型都包含一个内部指针,指向Object.prototype,这也正是所有自定义类型会继承toString()、ValueOf()等默认方法的根本原因。换句话说Object.prototype就是原型链的末端。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd717a5.jpg)
**2、确定原型和实例的关系**
通过两种方式可以确定原型和实例之间的关系,第一种是使用instanceOf操作符,第二种是使用isPrototypeOf()方法。
实例 instanceOf 原型链 中出现过的构造函数,都会返回true
console.log(person instanceOf Child);//true
console.log(person instanceOf Parent);//true
console.log(person instanceOf Object);//true
isPrototype(),只要是原型链中出现过的原型,都可以说是该原型链所派生出来的实例的原型,因此也返回true.
console.log(Object.prototype.isPrototypeOf(instance));//true
console.log(Parent.prototype.isPrototypeOf(instance));//true
console.log(Child.prototype.isPrototypeOf(instance));//true
**3、谨慎地定义方法**
子类型有时候需要覆盖超类型中的某个方法,或者需要添加超类型中不存在的莫个方法,注意:给原型添加方法的代码一定要放在替换原型的语句之后。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd88cd9.jpg)
当通过Child的实例调用getParentValue()时,调用的是这个重新定义过的方法,但是通过Parent的实例调用getParentValue()时,调用的还是原来的方法。
格外需要注意的是:必须要在Parent的实例替换原型之后,再定义这两个方法。
还有一点需要特别注意的是:通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样做会重写原型链。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd9be26.jpg)
以上代码刚把Parent的实例赋值给Child的原型对象,紧接着又将原型替换成一个字面量,替换成字面量之后,Child原型实际上包含的是一个Object的实例,而不再是Parent的实例,因此我们设想中的原型链被切断.Parent和Child之间没有任何关联。
**4、原型链的问题**
原型链很强大,可以利用它来实现继承,但是也有一些问题,主要的问题还是包含引用类型值的原型属性会被所有实例共享。因此我们在构造函数中定义实例属性。但是在通过原型来实现继承时,原型对象其实变成了另一个类型的实例。于是原先定义在构造函数中的实例属性变成了原型属性了。
举例说明如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fdb2b57.jpg)
在Parent构造函数中定义了一个friends属性,该属性值是一个数组(引用类型值)。这样,Parent的每个实例都会各自包含自己的friends属性。当Child通过原型链继承了Parent之后,Child.prototype也用用了friends属性——这就好像friends属性是定义在Child.prototype一样。这样Child的所有实例都会共享这个friends属性,因此我们对kid1.friends做的修改,在kid2.friends中也会体现出来,显然,这不是我们想要的。
原型链的另一个问题是:在创建子类型的实例时,不能在不影响所有对象实例的情况下,给超类型的构造函数传递参数。因此,我们通常很少会单独使用原型链。
### 借用构造函数
为了解决原型中包含引用类型值带来的一些问题,引入了借用构造函数的技术。这种技术的基础思想是:在子类型构造函数的内部调用超类型构造函数。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fdc6ae5.jpg)
Parent.call(this)在新创建的Child实例的环境下调用了Parent构造函数。在新创建的Child实例环境下调用Parent构造函数。这样,就在新的Child对象上,此处的kid1和kid2对象上执行Parent()函数中定义的对象初始化代码。这样,每个Child实例就都会具有自己的friends属性的副本了。
借用构造函数的方式可以在子类型的构造函数中向超类型构造函数传递参数。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fdd9a82.jpg)
为了确保子类型的熟悉不会被父类的构造函数重写,可以在调用父类构造函数之后,再添加子类型的属性。
构造函数的问题:
构造函数模式的问题,在于方法都在构造函数中定义,函数复用无从谈起,因此,借用构造函数的模式也很少单独使用。
### 组合继承
组合继承指的是将原型链和借用构造函数的技术组合在一块,从而发挥二者之长。即:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fdeb002.jpg)
Person构造函数定义了两个属性:name和friends。Person的原型定义了一个方法sayName()。Child构造函数在调用Parent构造函数时,传入了name参数,紧接着又定义了自己的属性age。然后将Person的实例赋值给Child的原型,然后又在该原型上定义了方法sayAge().这样,两个不同的Child实例既分别拥有自己的属性,包括引用类型的属性,又可以使用相同的方法了。
组合继承避免了原型链和构造函数的缺陷,融合了他们的有点,成为JavaScript中最常用的继承模式。而且,instanceOf和isPropertyOf()也能够识别基于组合继承创建的对象。
最后,关于JS对象和继承都还有几种模式没有写,或者说,我自己也还未去深刻研究,但是,我想,首先将组合模式应用的游刃有余。并且,对于为何选用组合模式,知其然,知其所以然。
JS创建对象几种不同方法详解
最后更新于:2022-04-01 11:56:23
### 1、工厂模式
弊端:没有解决对象的识别问题,即怎么知道一个对象的类型。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc76f7a.jpg)
### 2、构造函数模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc89748.jpg)
与工厂模式相比:
1、没有显式的创建对象
2、直接将属性和方法赋给了this对象
3、没有return语句
要创建person的实例,必须使用new操作符,以这种方式调用构造函数实际上会经历4个步骤:
1、创建一个新对象
2、将构造函数的作用域赋给新对象
3、执行构造函数中的代码
4、返回新对象
创建自定义的构造函数可以将它的实例标识为一种特定的类型。
**构造函数的缺点:**
每个方法都有在每个实例上重新创建一遍。person1和person2都有一个sayName()的方法,但两个方法不是同一个Function实例。不同实例上的同名函数是不相等的。
创建两个完成同样任务的Function实例没有必要,而且还有this对象在,不需要在执行代码前就把函数绑定在特定对象上,可以像下面这样。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc9cb44.jpg)
把sayName属性设置成全局的sayName函数,这样,由于sayName包含的是一个指向函数的指针,因此person1和person2对象就共享了同一个函数。
但是,如果对象需要定义很多方法,那么就要定义很多全局函数,自定义的引用类型也没有封装可言了。为了解决上述问题,引入原型模式。
### 3、原型模式
**理解原型对象**
我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的对象原型,使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fcabb4e.jpg)
首先,解析器会问实例person1是否有name属性,如果有,就返回。
如果没有,就继续去person1的原型中搜索name属性,如果有就返回。
如果没有,再继续向person1的原型的原型中搜索。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fcbe3dd.jpg)
**isPrototypeOf()确定实例和原型对象之间的关联**
console.log(Person.prototype.isPrototypeOf(person1)); //true
**Object.getPrototypeOf()返回的是[[prototype]]的值**
console.log(Object.getPrototypeOf(person1));
//Person {name: “Yvette”, age: 26, job: “engineer”} 返回的是Person的原型对象。
console.log(Object.getPrototypeOf(person1) === Person.prototype)//true
console.log(Object.getPrototypeOf(person1).name);//”Yvette”
**hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中,只有给定属性存在于实例中,才会返回true。**
console.log(person1.hasOwnProperty(“name”));//false
**原型与in操作符**
有两种方式使用in操作符:单独使用和在for-in循环中使用。单独使用时,in操作符会在通过对象能够访问给定属性时返回true,无论该属性在于实例中还是原型中。
使用for in循环,返回的是所有能够通过对象访问的、可枚举的属性,其中既包括实例中的属性,也包括存在于原型中的属性。如果实例中的属性屏蔽了原型中不可枚举的属性,那么也会返回。IE9之前的版本实现上有一个Bug,屏蔽不可枚举属性的实例属性不会在for-in中返回。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fcd47cc.jpg)
在IE9之前的吧按本中没有log信息。尽管person实例中的toString()方法屏蔽了原型中的不可 枚举的toString();
**原型简写**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fce52b4.jpg)
这导致了person1.constructor不再指向Person,而是指向了Object。如果constructor很重要,则需要特意将其设为适当的值,如:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd04a77.jpg)
但是这种方式会导致constructor属性变成可枚举。
如果想设置为不可枚举的(默认不可枚举),可以使用Object.defineProperty(Person.prototype, “constructor”, {
enumerable: false,
value: Person
});
**原型的动态性**
由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来。
如果重写整个原型对象,情况就不一样了。调用构造函数时会为实例添加一个指向最初原型的[[prototype]]指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。实例中的指针仅指向原型,而不指向构造函数。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd168e8.jpg)
person.prototype指向的是原本的原型对象,而不会指向新的原型对象。
**原型对象的问题**
原型模式最大问题是由其共享的本性所导致的。
对于包含引用类型值的属性来说,问题较为突出
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd242cb.jpg)
本意只想修改person1的friends,但是却导致person2的friends属性值也改变了。因此我们很少单独使用原型模式。
### 4、组合使用构造模式和原型模式
创建自定义类型的最常用的方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性,这样每个实例都有自己的一份实例属性的副本,又同时共享着对方法的引用,最大限度的节省了内存。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fd364b0.jpg)
除了以上几种方式以外,另外还有动态原型模式,寄生构造模式和稳妥构造模式,但是鉴于使用频率较低,不再赘述。
CSS3的border-radius属性详解
最后更新于:2022-04-01 11:56:20
border-radius: none | length{1,4} [/ length{1,4}
其中每一个值可以为 数值或百分比的形式。
length/length 第一个lenght表示水平方向的半径,而第二个表示竖直方向的半径。
如果是一个值,那么 top-left、top-right、bottom-right、bottom-left 四个值相等。
如果是两个值,那么 top-left和bottom-right相等,为第一个值,top-right和bottom-left值相等,为第二个值。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fbecef0.jpg)
如果是三个值,那么第一个值是设置top-left,而第二个值是 top-right 和 bottom-left 并且他们会相等,第三个值是设置 bottom-right。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc0a570.jpg)
如果是四个值,那么第一个值是设置 top-left, 而第二个值是 top-right 第三个值 bottom-right 第四个值是设置 bottom-left
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc1c775.jpg)
**除了上述的简写外,还可以和border一样,分别写四个角,如下:**
border-top-left-radius: //左上角
border-top-right-radius: //右上角
border-bottom-right-radius: //右下角
border-bottom-left-radius: //左下角
分别是水平方向和竖直方向半径,第二值省略的情况下,水平方向和竖直方向的半径相等。
border-radius 只有在以下版本的浏览器:Firefox4.0+、Safari5.0+、Google Chrome 10.0+、Opera 10.5+、IE9+ 支持 border-radius 标准语法格式,对于老版的浏览器,border-radius 需要根据不同的浏览器内核添加不同的前缀,比说 Mozilla 内核需要加上“-moz”,而 Webkit 内核需要加上“-webkit”等,但是IE和Opera没有私有格式,因此为了最大程度的兼容浏览器,我们需要设置如下:
-webkit-border-radius: 10px 20px 30px;
-moz-border-radius: 10px 20px 30px;
border-radius: 10px 20px 30px;
**请将标准形式写在浏览器私有形式之后。**
举几个例子看一下效果:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
img{border-radius: 30px;margin: 100px;}
</style>
</head>
<body>
<img src="../images/photo.jpg" width="300px">
</body>
</html>
~~~
效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc30449.jpg)
四个角的半径都是30px;
再看一个标准的圆以及椭圆:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
div{display: inline-block; border: 10px solid red;}
.circle{width: 50px; height: 50px;
-webkit-border-radius:50%;-moz-border-radius:50%;border-radius: 50%;}
.elipse{width: 50px; height: 100px;
-webkit-border-radius:50%;-moz-border-radius:50%;border-radius: 50%;}
</style>
</head>
<body>
<div class="circle"></div>
<div class="elipse"></div>
</body>
</html>
~~~
效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc51478.jpg)
第一个和第二个div的差别主要在于其是正方形还是长方形,圆圈在轮播时,可以替代圆圈的图片使用。
以上都是水平方向和竖直方向半径相等的例子,下面举两个水平方向和竖直方向半径不相同的例子:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
div{display: inline-block; border: 10px solid red;margin: 100px;}
.div1{width: 200px; height: 100px;border-radius: 0px 50px 32px/28px 50px 70px;}
.div2{width:100px; height: 200px; border-radius: 26px 106px 162px 32px/28px 80px 178px 26px;}
.div3{width:100px;height: 200px; border-radius: 20px 50px/ 20px 50px;}
</style>
</head>
<body>
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
</body>
</html>
~~~
效果如下所示:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fc6190c.jpg)
CSS3新增颜色属性
最后更新于:2022-04-01 11:56:18
### CSS颜色属性复习
color name 颜色英文名称命名(如red,blue,pink,white等)
HEX方式 十六进制方式(#FF0000,#B9B9B9等)
rgb方式 三原色配色方式(rgb(255,0,00))
这几种方式都是常用到的颜色属性,本人使用较多的是HEX方式。CSS3中新增了几种颜色属性。
### CSS3新增颜色属性
1、RGBA模式
2、HSL模式
3、HSLA模式
**1、RGBA模式**
rgba在之前一遍博客中已经提及过,a表示的是透明度,取值范围为0~1,rgb分别是红绿蓝三色,取值范围均为0~255.
**2、HSL模式**
H: Hue(色调)。
0(或360)表示红色,120表示绿色,240表示蓝色,也可取其他数值来指定颜色。取值为:0 - 360
S: Saturation(饱和度)。取值为:0.0% - 100.0%
L: Lightness(亮度)。取值为:0.0% - 100.0%
**3、HSLA模式**
HSL与HSL模式的相同,增加A,即透明度
A: alpha 透明度 0~1之间
HSL的色轮如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fbb03de.jpg)
举例看个HSLA
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
div{width:100px;height:100px;background: HSLA(0,100%,60%,0.5);}
</style>
</head>
<body>
<div></div>
</body>
</html>
~~~
效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fbd8e2f.jpg)
个人觉得HSL与RGB和HEX相比,颜色更容易记忆,但是鉴于通过我们都是使用取色器,所以觉得意义不大,还是会继续使用RGBA和HEX方式。而HSL和HSLA仅是做一个了解。
利用CSS3实现图片切换特效
最后更新于:2022-04-01 11:56:16
利用label标签和:checked,并使用到了transform和transition属性。实现简单,相比JS而言,非常方便,且效果更佳,有兴趣可以拷贝代码,修改图片路径,运行看看效果。
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
#content{width:800px;margin: 30px auto;position: relative;}
input[type="radio"]{display: none;}
input[type="radio"]~img{width: 800px;position: absolute;top:0px;left:0px;opacity: 0;height: 500px;transform:scale(1.1);transition:all 1s;}
input:checked +label + img{opacity: 1;transform:scale(1.0);}
input:checked +label img{border: 8px solid #FFDA34; opacity: 1.0; transition: all 1s;}
label {display: inline-block;width: 134px;margin: 5px 8px;}
label img{ opacity:0.5; width: 134px; margin-top:500px;height: 75px;border:8px solid #000;}
</style>
</head>
<body>
<div id = "content">
<input type = "radio" name="carousel" id = "list1" checked>
<label for="list1">
<img src="../images/photo1.jpg">
</label>
<img src="../images/photo1.jpg">
<input type = "radio" name="carousel" id = "list2">
<label for="list2">
<img src="../images/photo2.jpg">
</label>
<img src="../images/photo2.jpg">
<input type = "radio" name="carousel" id = "list3">
<label for="list3">
<img src="../images/photo3.jpg">
</label>
<img src="../images/photo3.jpg">
<input type = "radio" name="carousel" id = "list4">
<label for="list4">
<img src="../images/photo4.jpg">
</label>
<img src="../images/photo4.jpg">
<input type = "radio" name="carousel" id = "list5">
<label for="list5">
<img src="../images/photo5.jpg">
</label>
<img src="../images/photo5.jpg">
</div>
</body>
</html>
~~~
静态的效果图如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fb55e43.jpg)
CSS3新增文本属性详述
最后更新于:2022-04-01 11:56:13
### CSS文本属性复习
1、white-space:对象内空格的处理方式
2、direction:文本流的方向
3、unicode-bidi:用于同一个页面里存在从不同方向读进的文本显示。与direction属性一起使用
1.white-space:对象内空格的处理方式
nowrap 控制文本不换行
pre 空白会被浏览器保留
normal 默认状态
pre-line 合并空白 保留换行符
pre-wrap 保留空白 正常换行
nowrap经常配合text-overflow一起使用,使得超出部分显示为省略号,主要overflow一定要设置为hidden,如下:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{
width: 200px;font-size: 20px;
white-space: nowrap;text-overflow: ellipsis;overflow: hidden;
}
</style>
</head>
<body>
<p title="被包围在pre元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体">
被包围在pre元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体</p>
</body>
</html>
~~~
效果如下图所示:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa4dc95.jpg)
还可以在样式中增加p:hover{normal;}这样正常状态下超出部分显示省略号,而鼠标悬停在p之上时,显示完整内容。
再看下其它的几个属性:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{width: 400px;font-size: 18px; background: #CBFF8F;line-height: 36px;}
.pre{white-space: pre;/*空白被浏览器保留*/}
.pre-line{white-space: pre-line;/*合并空白,保留换行符*/}
.pre-wrap{white-space: pre-wrap;/*保留空白,正常换行*/}
</style>
</head>
<body>
<p class="pre"> 在理解this绑定之前, 先要理解调用位置。
我们可以通过浏览器的调试工具来查看调用栈。
在第一行代码钱插入一条debugger;</p>
<p class="pre-line"> 在理解this绑定之前, 先要理解调用位置。
我们可以通过浏览器的调试工具来查看调用栈。
在第一行代码钱插入一条debugger;</p>
<p class="pre-wrap"> 在理解this绑定之前, 先要理解调用位置。
我们可以通过浏览器的调试工具来查看调用栈。
在第一行代码钱插入一条debugger;</p>
<p class="normal"> 在理解this绑定之前, 先要理解调用位置。
我们可以通过浏览器的调试工具来查看调用栈。
在第一行代码钱插入一条debugger;</p>
</body>
</html>
~~~
效果图如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa5fb57.jpg)
如果元素内容未超出范围,pre和pre-wrap的效果是一样的,只有超出范围时,才有区别,pre是不会自动换行的,而pre-wrap到元素边界处,自动换行。
**2、direction:文本流的方向**
ltr 文本从左向右
rtl 文本从右往左
~~~
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{background: #e3e3e3;padding: 5px; width: 200px;}
.left{direction: ltr;}
.right{direction: rtl;}
</style>
</head>
<body>
<p class="left">文本流的方向</p>
<p class="right">文本流的方向</p>
<p>文本流的方向</p>
</body>
</html>
~~~
效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa75e49.jpg)
**3、unicode-bidi:用于同一个页面里存在从不同方向读进的文本显示。 与direction属性一起使用**
bidi-override 严格按照 属性的值重排序。忽略隐式双向运算规则。
unicode-bidi默认的属性值为normal,此外,在CSS3中还增加了另外几个属性值: isolate 、 isolate-override 、plaintext
仅举例说明bidi-override:(unicode-bidi属性在项目中使用频率很低)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{background: #e3e3e3;padding: 5px; width: 200px;}
.left{direction: ltr;unicode-bidi: bidi-override;}
.right{direction: rtl;unicode-bidi: bidi-override;}
</style>
</head>
<body>
<p class="left">文本流的方向</p>
<p class="right">文本流的方向</p>
</body>
</html>
~~~
效果如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa85405.jpg)
**CSS3新增文本属性**
1、color:rgba();
2、text-overflow:是否使用一个省略标记(…)标示对象内文本的溢出
3、text-align:文本的对齐方式
4、text-transform:文字的大小写
5、text-decoration:文本的装饰线,复合属性
6、text-shadow:文本阴影
7、text-fill-color:文字填充颜色
8、text-stroke:复合属性。设置文字的描边
9、tab-size:制表符的长度
10、word-wrap:当前行超过指定容器的边界时是否断开转行
**1、rgba()**
r red 红色 0-255
g green 绿色 0-255
b blue 蓝色 0-255
a alpha 透明 0-1
rgba比rgb增加了一个透明度,此前我们使用opacity设置透明度,但是使用opacity会使得文字也变得透明,而rgba则不会,如下:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
div{font-size: 24px; width: 200px; font-weight: 600; margin: 20px;
height: 200px; line-height: 200px;text-align: center;float: left;}
.div1{background:rgb(0,146,255); opacity: 0.5;}
.div2{background: rgba(0,146,255,0.5);}
.img{width:400px;height:300px;
background: url(../images/photo2.jpg) center;
border: 25px solid rgba(0,0,0,0.6);}
</style>
</head>
<body>
<div class="div1">文本属性</div>
<div class="div2">文本属性</div>
<div class="img"></div>
</body>
</html>
~~~
效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa9bfee.jpg)
**2、text-overflow:是否使用一个省略标记(…)标示对象内文本的溢出**
clip: 默认值 无省略号
ellipsis:当对象内文本溢出时显示省略标记(…)。
注意:该属性需配合over-flow:hidden属性(超出处理)还有white-space:nowrap(禁止换行)配合使用,否则无法看到效果
这部分在前面讲white-space时已有例子。
**3、text-align:文本的对齐方式**
css1
left:默认值 左对齐
right:右对齐
center:居中
justify: 内容两端对齐。
css3
start:开始边界对齐
end:结束边界对齐
(跟文本流方向有关,如果文本流的方向为自右向左,那么start就是右侧,end就是左侧)
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{width:200px;background: #27bde3;padding: 5px;}
.left{text-align: left;}
.right{text-align: right;}
.center{text-align: center;}
.justify{text-align: justify;}
.start{text-align: start; direction: rtl;}
.end{text-align: end;}
</style>
</head>
<body>
<p class="left">文本的对齐方式</p>
<p class="right">文本的对齐方式</p>
<p class="center">文本的对齐方式</p>
<p class="justify">文本的对齐方式ssssssssssss</p>
<p class="start">文本的对齐方式</p>
<p class="end">文本的对齐方式</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603facbc62.jpg)
**4、text-transform:文字的大小写**
css1
none: 默认值 无转换
capitalize: 将每个单词的第一个字母转换成大写
uppercase: 转换成大写
lowercase: 转换成小写
css3
full-width: 将左右字符设为全角形式。不支持
full-size-kana:将所有小假名字符转换为普通假名。不支持
例如:土耳其语。
这几个属性值都可以从描述中清晰的看出其用途,不做举例说明
**5、text-decoration:文本的装饰线,复合属性**
text-decoration-line :指定文本装饰的种类。相当于CSS1时的text-decoration属性
none:指定文字无装饰
underline: 指定文字的装饰是下划线
overline:指定文字的装饰是上划线
line-through: 指定文字的装饰是贯穿线
text-decoration-style :指定文本装饰的样式。
solid:实线
double:双线
dotted:点状线条
dashed:虚线
wavy:波浪线
text-decoration-color:指定文本装饰的颜色。
用法:text-decoration : #F00 double overline
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{font-size: 24px;}
.under{text-decoration: #FA4C41 dotted underline;}
.over{text-decoration: #0092ff solid overline;}
.through{text-decoration: #FF0000 double line-through;}
.dashed{text-decoration: #FF0000 dashed underline;}
.wavy{text-decoration: #FF0000 wavy underline;}
</style>
</head>
<body>
<p class="under">IE不支持这个属性</p>
<p class="over">IE不支持这个属性</p>
<p class="through">IE不支持这个属性</p>
<p class="dashed">IE不支持这个属性</p>
<p class="wavy">IE不支持这个属性</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fadbdc8.jpg)
**6、text-shadow:文本阴影**
取值:x y blur color,……
x 横向偏移
y 纵向偏移
blur 模糊距离(灰度)
color 阴影颜色
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{text-align:center;font:50px/50px "微软雅黑";/*字体:字体大小/行高*/}
.p1{font-weight:600; text-shadow: 5px 4px 8px #766F5A;}
.p2{color:#FFF;text-shadow:2px 3px 4px #000;/**/}
.p3{color: #FFF; text-shadow: 0 0 20px #FF79C3, 0 0 30px #71FF5B,0 0 50px #FF0000,0 0 80px #FF0000;}
</style>
</head>
<body>
<p class="p1">文本阴影</p>
<p class="p2">浮雕效果</p>
<p class="p3">光影效果</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603faf3be2.jpg)
**7、text-fill-color:文字填充颜色**
兼容性不好,目前仅谷歌支持。
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{-webkit-text-fill-color:red;font-size:30px;font-weight: 600;}
</style>
</head>
<body>
<p>文字填充颜色</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fb18e0e.jpg)
**8、text-stroke:复合属性。设置文字的描边**
text-stroke-width:文字的描边厚度
text-stroke-color:文字的描边颜色
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{font-size:100px;-webkit-text-fill-color: transparent;
-webkit-text-stroke: 2px blue;}
</style>
</head>
<body>
<p>描边属性</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fb28680.jpg)
**9、tab-size:制表符的长度**
默认值为8(一个tab键的空格字节长度),在pre标签之内才会有显示
**10、word-wrap:当前行超过指定容器的边界时是否断开转行**
normal: 默认值
允许内容顶开或溢出指定的容器边界。
break-word:
内容将在边界内换行。如果需要,单词内部允许断行。
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
p{width:200px;border:2px solid #FF0000;padding: 5px;}
.p1{word-wrap: normal}
.p2{word-wrap: break-word;}
</style>
</head>
<body>
<p class="p1">Farawayfromme,awayfromharmaaa</p>
<p class="p2">Farawayfromme,awayfromharmaaa</p>
</body>
</html>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fb3d580.jpg)
鉴于CSS3的兼容性问题,可以在caniuse网站进行查询,以明确其支持的浏览器版本。
[http://caniuse.com/](http://caniuse.com/)
CSS3选择器(全)
最后更新于:2022-04-01 11:56:11
### CSS选择器复习
通用选择器:* 选择到所有的元素
选择子元素:> 选择到元素的直接后代(第一级子元素)
相邻兄弟选择器:+ 选择到紧随目标元素后的第一个元素
普通兄弟选择器:~ 选择到紧随其后的所有兄弟元素
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f98e9e0.jpg)
**伪元素选择器**:
::first-line 匹配文本块的首行
::first-letter 选择文本块的首字母
伪类选择器:
:before, :after在元素内容前面、后面添加内容(相当于行内元素)
CSS3结构选择器
:nth-child 选择指定索引处的子元素
nth-child(n) 父元素下的第n个子元素
nth-child(odd) 奇数子元素(同nth-child(2n-1))
nth-child(even) 偶数子元素(同nth-child(2n))
nth-child(an+b) 公式
(nth-child从1开始)
:nth-last-child(n) 倒数第n个子元素
:nth-of-type(n) 父元素下的第n个指定类型的子元素
:nth-last-of-type 父元素下的倒数第n个指定类型的子元素
:first-child 选择父元素下的第一个子元素
:last-child 选择父元素下的最后一个子元素
:only-child 选择父元素下唯一的子元素
:only-of-type 选择父元素下指定类型的唯一子元素
:root 选择文档的根目录,返回html
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f9a34b8.jpg)
div :only-child注意空格(选中div下唯一的子元素)
**伪类选择器**
:link指向未被访问页面的链接设置样式
:visited设置指向已访问页面的链接的样式
:hover鼠标悬停时触发
:active在点击时触发
:enabled 选择启用状态元素
:disabled 选择禁用状态元素
:checked 选择被选中的input元素(单选按钮或复选框)
:default 选择默认元素
:valid、invalid 根据输入验证选择有效或无效的input元素
:in-range、out-of-range 选择指定范围之内或者之外受限的元素
:repuired、optional 根据是否允许:required属性选择input元素
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f9b654c.jpg)
如果将link的颜色设置的与visited相同,则页面打开时,link的样式被visited样式覆盖,如上,a标签显示的字体颜色为绿色。
但是如果设置为不同的属性,可以呈现出叠加的效果。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f9c97e3.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f9de323.jpg)
点击a标签时,字体的颜色为黄色。
利用label修改radio的样式:如下:
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
input[type="radio"]{display: none;}
label{display: inline-block;width: 24px;height: 24px;
border-radius: 50%;border: 1px solid #ccc;margin: 5px;}
:checked + label{background: #00b3ee;}
</style>
</head>
<body>
<input type="radio" name = "fruit" id = "check1"/>
<label for="check1"></label>
<input type="radio" name = "fruit" id = "check2"/>
<label for="check2"></label>
<input type="radio" name = "fruit" id = "check3"/>
<label for="check3"></label>
<input type="radio" name = "fruit" id = "check4"/>
<label for="check4"></label>
</body>
</html>
~~~
实现的效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f9f01a7.jpg)
**:default**
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Keywords" content="关键词一,关键词二">
<meta name="Description" content="网站描述内容">
<meta name="Author" content="刘艳">
<title></title>
<style>
:default{background: #009FE6;}
</style>
</head>
<body>
<form>
<input type="text">
<button>按钮</button>
<input type="submit" value="提交">
</form>
</body>
</html>
~~~
form表单中默认获取到焦点的是Button按钮
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa0e467.jpg)
属性选择器
E[attr] 属性名,不确定具体属性值
E[attr=”value”] 指定属性名,并指定其对应属性值
E[attr ~=”value”] 指定属性名,找到的是具有此属性名,且与其它属性名之间用空格隔开,如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa1f4e4.jpg)
E[attr ^= “value”] 指定属性名,属性值以value开头
E[attr $=”value”] 指定属性名,属性值以value结束
E[attr *=”value”] 指定了属性名,属性值中包含了value
E[attr |= “value”] 指定属性名,属性值以value-开头或者值为value
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603fa3200d.jpg)
JS字符串的相关方法
最后更新于:2022-04-01 11:56:09
###1、字符方法
charAt()和charCodeAt(),这两个方法都接收一个参数,及基于0的字符位置,charAt()返回的是给定位置的字符,charCodeAt()返回的是给定位置字符的字符编码。与charCodeAt()对应的一个方法是formCharCode()将字符编码转为字符串。
如:
~~~
<script>
var code = "future";
console.log(code.charAt(2)); //t
console.log(code.charCodeAt(2)) //116
</script>
~~~
除了以上方法外,还可以通过方括号去访问特定位置的字符,如:
~~~
<script>
var code = "future";
console.log(code[2]); //t
</script>
~~~
使用方括号的方法在IE8,Firefox,Safari,Chrome和Opera中都可以支持,但是在IE7及更早版本中不支持,返回的值为undefined.
### 2、字符串操作方法
1、字符串拼接:concact()方法。
~~~
var a = "my ";
console.log(a.concat("future"));//my future
console.log(a.concat("future ", "will"));//my future will
~~~
2、基于子字符串创建新字符串:slice()、substr()和substring().这三个方法都返回操纵字符串的一个子字符串,而且都接收一到两个参数。
第一个参数指定字符串的开始位置,第二个参数(可省略)表示子字符串到哪里结束。slice()和substring()的第二个参数指定的是子字符串最后一个字符后面的位置,而substr()的第二个参数指定的是返回的字符个数。如果省略第二个参数,则截取到字符串最后一个位置。
~~~
var str = "We are family";
console.log(str.slice(2,5)); // ar(从第2个位置开始,不包含第5个位置)
console.log(str.slice(1)); //e are family(从第1个位置开始,一直到最后)
console.log(str.substring(3)); //are family(从第3个位置开始,一直到最后)
console.log(str.substring(3,5));//ar(从第3个位置开始,不包含第5个位置)
console.log(str.substr(2)); // are family(从第2个位置开始,一直到最后)
console.log(str.substr(2,6)); // are f(从第2个位置开始,截取6个字符)
~~~
slice()和substring()方法在正值情况下,实现的功能一致,但是在传递的值为负值时,行为就不相同了。
slice()方法会将传入的负值与字符串的长度相加(因此,如果两个参数都会负值,第二个参数必须要大于第一个参数,否则返回的是空字符串)
substr()方法会将负的第一个参数加上字符串的长度,将将第二个参数转换为0。(如果第二个参数为负值,返回空的字符串)
substring()方法将所有的负值参数都转换为0,substring始终会将较小的参数作为开始位置。
~~~
var str = "Wearefamily"; //length为11
console.log(str.slice(-3,-8));//相当于str.slice(8,3)//返回空字符串
console.log(str.slice(-5,-1));//相当于str.slice(6,10)//返回ami
console.log(str.substring(3,-4));//相当于str.substring(3,0)//返回Wea
console.log(str.substring(-3,-5));//相当于str.substring(0,0)//返回空字符串
console.log(str.substr(-4,3));//相当于substr(7,3)//返回mil
console.log(str.substr(-4,-3));//相当于substr(7,0)//返回空字符串
~~~
### 3、字符串的位置方法
字符串的位置方法:indexOf()和lastIndexOf()。这两个方法都是从一个字符串中搜索给定的子字符串,然后返回子字符串的位置,没有找到,返回-1.indexOf()从字符串的开头向后搜索子字符串,而lastIndexOf()从字符串的末尾向前搜索子字符串。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f97a0a6.jpg)
~~~
var str = "WEAREFAMILY";
console.log(str.indexOf("A"));//2
console.log(str.lastIndexOf("A"));//6
~~~
### 4.trim()方法
trim()用于去掉字符串收尾的空格
### 5、字符串大小写转换方法
转换为大写:toUpperCase()和toLocalUpperCase()
转换为小写:toLowerCase()和toLocalLowerCase()
### 6、字符串的模式匹配
match(),replace(),search(),replace()以及split()方法是String类型定义的集中用于在字符串中匹配模式的几种方法。
match方法只接收一个参数,要么是一个正则表达式,要么是一个RegExp对象。在字符串上调用match()方法,本质上和调用RegExp的exec()方法相同,返回的是一个数组
~~~
var str = "we are weamy";
var pattern = /we/;
var matches = str.match(pattern);
console.log(matches);//["we", index: 0, input: "we are weamy"]
console.log(pattern.exec(str));//["we", index: 0, input: "we are weamy"]
console.log(matches.index);//0
console.log(matches[0]);//we
~~~
search()的参数与match()相同,不同在于search()返回的是字符串中第一个匹配项的索引;如果没有找到匹配项,返回-1.
replace()方法,接收2个参数,第一个参数可以是一个RegExp对象或者是一个字符串,第二个参数是一个字符串或者是一个函数,如果第一个参数是字符串,那么只会替换第一个字符串,如果想要替换所有的字符串,那么必须使用正则表达式,并指定全局标志(g)
~~~
var str = "cat, fat, sat, bat";
console.log(str.replace("at","ooo"));//cooo, fat, sat, bat
console.log(str.replace(/at/g,"ooo"));//cooo, fooo, sooo, booo
~~~
如果replace()的第二个参数是字符串,还可以使用一些特殊的字符序列,将正则表达式操作得到的值插入到结果字符中。
$$ $
S& 匹配整个模式的子字符串
Sn 匹配第n个捕获组的子字符串
~~~
var str = "cat, fat, sat, bat";
console.log(str.replace("at","ooo"));//cooo, fat, sat, bat
console.log(str.replace(/(.at)/g,"ooo ($1)"));//ooo (cat), ooo (fat), ooo (sat), ooo (bat)
console.log(str.replace(/(.at)/g,"ooo ($&)"));//ooo (cat), ooo (fat), ooo (sat), ooo (bat)
~~~
split()方法接收一个参数作为分隔符,将字符串转变为数组。
与之相对应的方法是join(),用作将数组转变为字符串。
### 7、LocalCompare()方法
这个方法用于字符串的比较。
如果字符串在字母表中应该拍照字符串参数之前,则返回一个负数。(大多数情况下是-1,具体的值要视实现而定)
如果字符串等于字符串参数,则返回0.
如果字符串在字母表中的顺序排在字符串参数之后,则返回一个正数。(大多数情况下是1,具体的值要视实现而定)
~~~
var str = "break";
console.log(str.localeCompare("future")); //-1
console.log(str.localeCompare("above")); //1
console.log(str.localeCompare("break")); //0
~~~
前端的上传下载
最后更新于:2022-04-01 11:56:06
此次项目有一个下载文件的功能。
好吧,有点发愣。
后来发现原来用a标签就可以。
啦啦啦。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-07_570603f961058.jpg)
在点击a标签的时候就会直接下载啦。
使用download属性的原因是因为 jpg txt文件浏览器认识,默认的操作是打开,而不是下载~~~~
好吧,知道了就很easy辣·····
上传文件,使用type = "file"的input控件。。。