天猫购物网站最显眼的就是轮播图了。我在学习一样新js库,一个新框架或新的编程思想的时候,总是感叹“入门必做选项卡,进阶须撸轮播图。”作为一个React组件,它是状态操控行为的典型,拿来练手是个不错的选择。

为了复习,这次就尝试用原生的javascript+React来完成。


轮播图原生实现

所谓轮播图其实是扩展版的选项卡。

先布局

主干架构

<div id="tabs">
<ul id="btns">
<li><a href="javascript:;"></a></li>
<li><a href="javascript:;"></a></li>
<li><a href="javascript:;"></a></li>
<li><a href="javascript:;"></a></li>
<li><a href="javascript:;"></a></li>
<li><a href="javascript:;"></a></li>
</ul>
<ul id="imgs">
<li><img src="images/banner1.jpg"></li>
<li><img src="images/banner2.jpg"></li>
<li><img src="images/banner3.jpg"></li>
<li><img src="images/banner4.jpg"></li>
<li><img src="images/banner5.jpg"></li>
<li><img src="images/banner6.jpg"></li>
</ul>
</div>

样式如下

/*css-reset*/
*{
margin:0;
padding: 0;
}
ul li{
list-style: none;
}
img{
border: none;
}
a{
text-decoration: none;
} /******************/
#tabs{
width: 1130px;
height: 500px;
margin: 100px auto;
position: relative;
overflow: hidden;
}
#tabs li{
float: left;
}
#tabs img{
width: 1130px;
height: 500px;
}
#btns{
position: absolute;
top:88%;
left:395px;
z-index: 9;
}
#btns a{
display: block;
width: 17px;
height: 17px;
background: rgba(0,0,0,0.3);
border-radius: 50%;
border: 2px solid rgba(0,0,0,0.3);
}
#btns li{
margin: 10px;
}

大概效果

纯javascript实现

事件

一个简单的轮播图包括多个事件。

  • 鼠标移入移出:当鼠标移出,或者是鼠标不在轮播图上面,执行自动播放
  • 当鼠标移入:不再自动播放,而且点击按钮会执行跳转到相应的页面。

渐变

因为6张图不是很多。所以考虑六张图全部做绝对定位,按照顺序叠加在一起。然再通过一个透明度的运动框架,实现之。

在此我选用这个运动框架:

function getStyle(obj,attr){
if(obj.crrentStyle){
return obj.currentStyle[attr];
//兼容IE8以下
}else{
return getComputedStyle(obj,false)[attr];
//参数false已废。照用就好
}
} function startMove(obj,json,fn){
//清理定时器
if(obj.timer){
clearInterval(obj.timer);
}
obj.timer=setInterval(function(){
var bStop=false;//如果为false就停了定时器!
var iCur=0;
// 处理属性值
for(var attr in json){
if(attr=='opacity'){
iCur=parseInt(parseFloat(getStyle(obj,attr))*100);
}else{
iCur=parseInt(getStyle(obj,attr));
}
//定义速度值
var iSpeed=(json[attr]-iCur)/8;
iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);
//检测停止:如果我发现某个值不等于目标点bStop就不能为true。
if(iCur!==json[attr]){
bStop=false;
}
if(attr=='opacity'){
obj.style[attr]=(iCur+iSpeed)/100;
obj.style.filter='alpha(opacity:'+(iCur+iSpeed)+')';
}else{
obj.style[attr]=iCur+iSpeed+'px';
}
}
//检测是否停止,是的话关掉定时器
if(bStop===true){
if(iCur==json[attr]){
clearInterval(obj.timer);
if(fn){
fn();
}
}
}
},30);
}

这个框架可以指定样式值进行渐变。

不得不说,这确实是一个很棒的运动框架。可以把它单独放在为一个名为move.js的文件中再引入。

根据这个思路写出原生的代码:

window.onload=function(){
var oTab=document.getElementById('tabs');
var oBtns=document.getElementById('btns');
var aBtns=document.getElementsByTagName('a');
var oImgs=document.getElementById('imgs');
var aImgsLi=oImgs.getElementsByTagName('li');
var bCheck=true;
var iNow=0; // 以下是初始化设置:
aBtns[0].style.background='rgba(255,255,255,0.5)';
aImgsLi[0].style.zIndex=6; function iNowlistener(){//改变的核心函数
// 初始化
for(var i=0;i<aBtns.length;i++){
aBtns[i].style.background='rgba(0,0,0,0.3)';
}
aBtns[iNow].style.background='rgba(255,255,255,0.5)';
for(var j=0;j<aBtns.length;j++){
aImgsLi[j].style.opacity=0;
if(j!==iNow){
aImgsLi[j].style.display='none';
}else{
aImgsLi[j].style.display='block';
startMove(aImgsLi[j],{'opacity':100});
}
}
} var timer=null;
timer=setInterval(function(){
if(bCheck){
if(iNow==5){//将最后一个变为0
iNow=0;
}else{
iNow++;
}
iNowlistener();
}else{
return false;
}
},2000); oTab.onmouseover=function(){
bCheck=false;
for(var i=0;i<aBtns.length;i++){
aBtns[i].index=i;
aBtns[i].onmouseover=function(){
if(this.index==iNow){
return false;
}else{
iNow=this.index;
iNowlistener();
}
};
} }; oTab.onmouseout=function(){
bCheck=true;
}; };

效果如下:



不得不说,原生的代码写起来好长好长。

很长吗?后面的更长。


React思路

以上原生代码已经经过了初步的封装——比如INowListener。但是在React的价值观来说,显然还需要进一步的封装。甚至重新拆分。最理想的情况是:顶层组件作为主干架构和状态机。下层组件接收状态并运行方法。

多少个组件?

在这个轮播图中,就三个组件。

- Tabs
-imgs
-btns
var Tabs=React.createClass({
render:function(){ return (
<div id="tabs">
<Btns/>
<Imgs/>
</div>
);
}
}); var Btns=React.createClass({
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var btnContent=
<li key={i.toString()}><a href="javascript:;"></a></li>
arr.push(btnContent);
}
return (
<ul id="btns">{arr}</ul>
)
}
}); var Imgs=React.createClass({
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var imgContent=
<li key={i.toString()}><img src={"images/banner"+(i+1)+".jpg"}/></li>
arr.push(imgContent);
console.log(arr)
}
return (
<ul id="imgs">{arr}</ul>
);
}
}); ReactDOM.render(
<Tabs/>,
document.getElementById('example')
)

这样写就把样式写出来了。

哪个是状态?

iNOW是状态。而且是最重要的状态!既然这样,就考虑把状态iNow放顶层。

鼠标悬停看起来也是状态,但悬停按钮上,触发iNow改变——因此还是iNow。

鼠标移入移出事件,应该是状态。但是这个移入移出的状态依赖于iNow。所以不能单独用。

需要哪些props?

构造组件时,为了灵活性,一般都不考虑把组件框架写死。比如图片张数,id名,等等都应该是props。但是这些暂时来说,都是次要的。

状态肯定是一个核心props,此外,底层设置状态的回调也是核心的props之一。

空谈太多无意义,接下来尝试实现!


自动按钮

现在先不考虑其它,单看按钮。

在插入文档之后,开启一个定时器,每隔2000ms执行一次状态更新。

setState的写法

那涉及到了iNow状态根据前一个状态更新,官方文档不建议这种写法:

this.setState({
return {
iNow:this.state.iNow+1
}
})

因为状态更新可能是异步的。这样写很容易出问题。

事实上,官网提供了这样的写法:

this.setState(function(prev,props){
return {
iNow:prev.iNow+1
}
})

在这里只用第一个参数就够了。

想当然的按钮

定时器应该是一个状态计算器。

所以按钮可以这么写:

var Btns=React.createClass({
getInitialState:function(){
return ({
iNow:0
})
},
componentDidMount:function(){
var _this=this;
setInterval(function(){
_this.setState(function(prev){
//console.log(prev)
if(prev.iNow==5){
return {
iNow:0
};
}else{
return {
iNow:prev.iNow+1
};
}
})
},2000);
},
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var btnContent=null;
if(i==this.state.iNow){
btnContent=
<li key={i.toString()}><a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a></li>
}else{
btnContent=
<li key={i.toString()}><a href="javascript:;"></a></li>
} arr.push(btnContent);
} return (
<ul id="btns">{arr}</ul>
);
}
});

按钮就实现了。

看起来不错,但是这样写可能在未来造成极大的不便。

悬停交互

再强调一次价值观这个概念,按照React的价值观,状态应该从顶层传下去,况且在这个案例中,顶层Tabs组件做一件事就够了:状态机,在Btn组件插入到文档之后,打开这个定时器。底层组件比如Btns根据状态每隔2000ms通过props刷新变化。

同时,我还要实现一个简单的交互功能:当鼠标悬停在Tabs上时,不再允许iNow自动更新。——可以做一个bCheck开关,当Tabs组件鼠标移入/移出时,触发bCheck的来回变化。

此处可能有个小问题,就是鼠标一道按钮组上时,会造成bCheck抖动。但是最后又变回false。所以认为不影响。

很自然想到,bCheck为false时,关闭定时器。但是这样做又等于浪费了定时器的功能,回调方法中一旦关掉定时器,再重新定时器就不是一般的麻烦了,为什么不直接在定时器做判断呢?所以我认为不应该让定时器停下来。只需要改变定时器计算iNow的行为就行了。

var Tabs=React.createClass({
getInitialState:function(){
return {
iNow:0,
bCheck:true//为false时不允许定时器计算更新iNow
}
},
setInow:function(){
var _this=this;
var timer=setInterval(function(){
if(_this.state.bCheck){
//console.log(_this.state.bCheck)
_this.setState(function(prev){
if(prev.iNow==5){
return {
iNow:0
};
}else{
return {
iNow:prev.iNow+1
};
}
});
}else{
console.log('该停了!')
return false;
} },2000); },
checkSwitch:function(){
this.setState(function(prev){
return {
bCheck:!prev.bCheck,
}
})
},
render:function(){
return (
<div id="tabs" onMouseOver={this.checkSwitch} onMouseOut={this.checkSwitch}>
<Btns iNow={this.state.iNow} setInow={this.setInow}/>
<Imgs/>
</div>
);
}
}); var Btns=React.createClass({
componentDidMount:function(){
this.props.setInow();//插入后就执行回调方法
},
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var btnContent=null;
if(i==this.props.iNow){
btnContent=
<li key={i.toString()}>
<a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
</li>
}else{
btnContent=
<li key={i.toString()}><a href="javascript:;"></a></li>
} arr.push(btnContent);
} return (
<ul id="btns">{arr}</ul>
);
}
});

图片动画

一件事三个步骤

图片组件虽说只是做一件事情(根据iNow渲染效果),但是也得分三步来做。

  • 首先,渲染前应该保证索引值非iNow的所有图片display为none。索引值为iNow的图片透明度为0。(初始化)

  • 其次,在首次插入文档完毕之后(componentDidMount),对第0张图执行startMove函数。

  • 第三,需要一个监听顶层iNow的方法。定时器已经给Btns组件用了,再用就会出错。

    留意到Imgs组件实际上只接受一个会变化的props那就是iNow。因此采用componentWillReceiveProps

生命周期方法

componentWillReceiveProps

组件接收到新的props时调用,并将其作为参数nextProps使用,此时可以更改组件propsstate

    componentWillReceiveProps: function(nextProps) {
if (nextProps.bool) {
this.setState({
bool: true
});
}
}

这里采用的两个组件周期方法都是组件真实存在时的方法。所以可以直接使用真实的DOM命令。

实现

var Tabs=React.createClass({
getInitialState:function(){
return {
iNow:0,
bCheck:true
};
},
setInow:function(){
var _this=this;
var timer=setInterval(function(){
if(_this.state.bCheck){
//console.log(_this.state.bCheck)
_this.setState(function(prev){
if(prev.iNow==5){
return {
iNow:0
};
}else{
return {
iNow:prev.iNow+1
};
}
});
}else{
console.log('该停了!')
return false;
} },2000); },
checkSwitch:function(){
console.log(this.state.bCheck)
this.setState(function(prev){
return {
bCheck:!prev.bCheck
};
});
},
render:function(){
return (
<div id="tabs"
onMouseOver={this.checkSwitch}
onMouseOut={this.checkSwitch}>
<Btns iNow={this.state.iNow}
setInow={this.setInow} />
<Imgs iNow={this.state.iNow}/>
</div>
);
}
}); var Btns=React.createClass({
componentDidMount:function(){
this.props.setInow();
}, render:function(){
var arr=[];
for(var i=0;i<6;i++){
var btnsContent=null;
if(i==this.props.iNow){
btnsContent=
<li key={i.toString()}>
<a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
</li>
}else{
btnsContent=
<li key={i.toString()}>
<a href="javascript:;"></a>
</li>
}
arr.push(btnsContent);
} return (
<ul id="btns">{arr}</ul>
);
}
}); var Imgs=React.createClass({
componentDidMount:function(){//刚开始加载时,就执行动画函数
var iNow=this.props.iNow;
var obj=document.getElementById('imgs').getElementsByTagName('li')[iNow].childNodes[0];
startMove(obj,{'opacity':100});
},
componentWillReceiveProps:function(nextProps){
var obj=document.getElementById('imgs').getElementsByTagName('li')[nextProps.iNow].childNodes[0];
//console.log(obj)
startMove(obj,{'opacity':100});
},
// this.startMove:startMove(),
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var imgsContent=null
if(i==this.props.iNow){
imgsContent=
<li key={i.toString()}>
<img style={{opacity:'0'}} src={'images/banner'+(i+1)+'.jpg'} />
</li>
arr.push(imgsContent);
}else{
imgsContent=
<li key={i.toString()}>
<img style={{display:'none'}} src={'images/banner'+(i+1)+'.jpg'} />
</li>
arr.push(imgsContent);
} } return (
<ul id="imgs">{arr}</ul>
)
}
}) ReactDOM.render(
<Tabs/>,
document.getElementById('example')
);

看起来Imgs组件已经很完备了。——就它的功能来说已经没有什么需要添加了。


鼠标悬停改变iNow

这个事件只能在底层组件Btns上实现。所以要拿到悬停的索引值。

然后通过回调,把该按钮的索引值设置为整个组件Tabs的状态iNow。

为了干这两件事,还是用一个changeInow(e)函数来包装它们。

给谁绑定?加什么事件?

为了忠实原来的代码。我给a标签加onMouseOver事件。

加了事件直接,秉承这React的核心价值观(一个组件只干一件事),我把get到的index值通过this.props.setInow传递回去。只要顶层的iNow变了,下面的组件不管什么状态,都会乖乖听话了。

如何获取当前悬停的索引值?

在Jquery很容易使用index方法来获取索引值。但是在原生方法中,还得费一番周章。

给所有a绑定一个onMouseOver事件,假设该事件方法的参数为e,那么e.target就是该参数的方法。

这需要写一个getIndex方法

...
getIndex:function(e){
var list=e.target.parentNode.parentNode.childNodes;
for(var i=0;i<list.length;i++){
if(list[i]===e.target.parentNode){
return i;
}
}
},
...

拿到索引值之后

——就把它设置为顶层的iNow。

既然决定通过this.props.setInow回调,那么还得传一个索引值参数,回到顶层稍微修改下方法,就实现了。

全部代码:

var Tabs=React.createClass({//顶层组件
getInitialState:function(){
return {
iNow:0,
bCheck:true
};
},
setInow:function(index){//核心状态计算工具:依赖定时器进行实时刷新
if(index!==undefined){//如果参数有内容。
this.setState({
iNow:index
});
}else{
var _this=this;
this.timer=setInterval(function(){
if(_this.state.bCheck){
//console.log(_this.state.bCheck)
_this.setState(function(prev){
if(prev.iNow==5){
return {
iNow:0
};
}else{
return {
iNow:prev.iNow+1
};
}
});
}else{
//console.log('该停了!')
return false;
}
},2000);
}
},
checkSwitch:function(){
//console.log(this.state.bCheck)
this.setState(function(prev){
return {
bCheck:!prev.bCheck
};
});
},
render:function(){
return (
<div id="tabs"
onMouseOver={this.checkSwitch}
onMouseOut={this.checkSwitch}>
<Btns iNow={this.state.iNow}
setInow={this.setInow} />
<Imgs iNow={this.state.iNow}/>
</div>
);
}
}); var Btns=React.createClass({
componentDidMount:function(){
this.props.setInow();
},
getIndex:function(e){//获取a的父级索引值
var list=e.target.parentNode.parentNode.childNodes;
for(var i=0;i<list.length;i++){
if(list[i]===e.target.parentNode){
return i;
}
}
},
changeInow:function(e){//回调方法
//console.log($(e.target).parent().index());
//console.log(this.getIndex(e));
var index=this.getIndex(e);
this.props.setInow(index)
}, render:function(){
var arr=[];
for(var i=0;i<6;i++){
var btnsContent=null;
var index=i;
if(i==this.props.iNow){
btnsContent=
<li key={i.toString()}>
<a onMouseOver={this.changeInow} style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
</li>
}else{
btnsContent=
<li key={i.toString()}>
<a onMouseOver={this.changeInow} href="javascript:;"></a>
</li>
}
arr.push(btnsContent);
} return (
<ul id="btns">{arr}</ul>
);
}
}); var Imgs=React.createClass({
componentDidMount:function(){//刚开始加载时,就执行动画函数
var iNow=this.props.iNow;
var obj=document.getElementById('imgs').getElementsByTagName('li')[iNow].childNodes[0];
startMove(obj,{'opacity':100});
},
componentWillReceiveProps:function(nextProps){
var obj=document.getElementById('imgs').getElementsByTagName('li')[nextProps.iNow].childNodes[0];
//console.log(obj)
startMove(obj,{'opacity':100});
},
// this.startMove:startMove(),
render:function(){
var arr=[];
for(var i=0;i<6;i++){
var imgsContent=null
if(i==this.props.iNow){
imgsContent=
<li key={i.toString()}>
<img style={{opacity:'0'}} src={'images/banner'+(i+1)+'.jpg'} />
</li>
arr.push(imgsContent);
}else{
imgsContent=
<li key={i.toString()}>
<img style={{display:'none'}} src={'images/banner'+(i+1)+'.jpg'} />
</li>
arr.push(imgsContent);
} } return (
<ul id="imgs">{arr}</ul>
)
}
}) ReactDOM.render(
<Tabs/>,
document.getElementById('example')
);

完善

我们要让这个组件可复用,换言之就是把之前写死的东西比如图片数量,样式,id名都变成Tabs的props属性。

这下工作量够了吧。原来50多行的东西改写完之后大概150多行。

var Tabs=React.createClass({//顶层组件
getInitialState:function(){
return {
iNow:0,
bCheck:true
};
},
setInow:function(index){//核心状态计算工具:依赖定时器进行实时刷新
if(index!==undefined){//如果参数有内容。
this.setState({
iNow:index
});
}else{
var _this=this;
this.timer=setInterval(function(){
if(_this.state.bCheck){
//console.log(_this.state.bCheck)
_this.setState(function(prev){
if(prev.iNow==this.props.nums-1){
return {
iNow:0
};
}else{
return {
iNow:prev.iNow+1
};
}
});
}else{
//console.log('该停了!')
return false;
}
},this.props.timer);
}
},
checkSwitch:function(){
//console.log(this.state.bCheck)
this.setState(function(prev){
return {
bCheck:!prev.bCheck
};
});
},
render:function(){
return (
<div id={this.props.idNames.main}
onMouseOver={this.checkSwitch}
onMouseOut={this.checkSwitch}> <Btns iNow={this.state.iNow}
setInow={this.setInow}
nums={this.props.nums}
idNames={this.props.idNames} /> <Imgs iNow={this.state.iNow}
nums={this.props.nums}
idNames={this.props.idNames}
imgType={this.props.imgType} /> </div>
);
}
}); var Btns=React.createClass({
componentDidMount:function(){
this.props.setInow();
},
getIndex:function(e){//获取a的父级索引值
var list=e.target.parentNode.parentNode.childNodes;
for(var i=0;i<list.length;i++){
if(list[i]===e.target.parentNode){
return i;
}
}
},
changeInow:function(e){//回调方法
//console.log($(e.target).parent().index());
//console.log(this.getIndex(e));
var index=this.getIndex(e);
this.props.setInow(index)
}, render:function(){
var arr=[];
for(var i=0;i<this.props.nums;i++){
var btnsContent=null;
var index=i;
if(i==this.props.iNow){
btnsContent=
<li key={i.toString()}>
<a onMouseOver={this.changeInow} id={this.props.idNames.active} href="javascript:;"></a>
</li>
}else{
btnsContent=
<li key={i.toString()}>
<a onMouseOver={this.changeInow} href="javascript:;"></a>
</li>
}
arr.push(btnsContent);
} return (
<ul id={this.props.idNames.btns}>{arr}</ul>
);
}
}); var Imgs=React.createClass({
componentDidMount:function(){//刚开始加载时,就执行动画函数
var iNow=this.props.iNow;
var obj=document.getElementById(this.props.idNames.imgs).getElementsByTagName('li')[iNow].childNodes[0];
startMove(obj,{'opacity':100});
},
componentWillReceiveProps:function(nextProps){//每当收到新的props就执行动画
var obj=document.getElementById(this.props.idNames.imgs).getElementsByTagName('li')[nextProps.iNow].childNodes[0];
//console.log(obj)
startMove(obj,{'opacity':100});
}, render:function(){
var arr=[];
for(var i=0;i<this.props.nums;i++){
var imgsContent=null;
var src=this.props.imgType.url+this.props.imgType.name+(i+1)+'.'+this.props.imgType.type;
if(i==this.props.iNow){
imgsContent=
<li key={i.toString()}>
<img style={{opacity:'0'}} src={src} />
</li>
arr.push(imgsContent);
}else{
imgsContent=
<li key={i.toString()}>
<img style={{display:'none'}} src={src} />
</li>
arr.push(imgsContent);
}
} return (
<ul id={this.props.idNames.imgs}>{arr}</ul>
)
}
}) ReactDOM.render(
<Tabs
nums={6}
timer={2000}
idNames={
{
main:"tabs",
btns:"btns",
imgs:"imgs",
active:"btn-active"
}
}
imgType={
{
type:"jpg",
url:"images/",
name:"banner"
}
}
/>,
document.getElementById('example')
);

其中多设置了一个#btn-active样式。

#btn-active{
background:rgba(255,255,255,0.5)!important;
}

是不是好长好长呢?

demo地址:

http://djtao.top/tabs/

但是这个确实是一个可复用的,而且还是原生js写成的组件。

不得不说,作为一个初学几天的人,写这东西时的时候遭遇好多的坑。但是最后“蓦然回首,那人却在灯火阑珊处”,也有种人生三境界的感悟了!

React视角下的轮播图的更多相关文章

  1. React Native 如何做轮播图 react-native-swiper

    //:仿饿了么github:https://github.com/stoneWeb/elm-react-native 欢迎各位同学加入: React-Native群:397885169 大前端群:54 ...

  2. React 轮播图实现

    接到项目, 用react和material-ui实现轮播图. 搜索了一些方法参考, 不论语言/框架的使用,大体上分为两种思路 超宽列表实现法 在原生JS或者JQuery中,轮播图的实现一般是这样子的 ...

  3. React中使用CSSTransitionGroup插件实现轮播图

    动画效果,是一个页面上必不可少的功能,学习一个新的东西,当然就要学习,如何用新的东西,用它的方法去实现以前的东西啦.今天呢,我就在这里介绍一个试用react-addons-css-transition ...

  4. React Native学习(六)—— 轮播图

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  5. reactjs-swiper react轮播图组件基于swiper

    react轮播图组件基于swiper demo地址:http://reactjs-ui.github.io/reactjs-swiper/simple.html 1. 下载安装 npm install ...

  6. react轮播图----react-slick

    1.安装 npm install react-slick; //安装样式 npm install slick carousel; 再在App.css中引入 @import "~slick-c ...

  7. React Native 之轮播图swiper组件

    注释:swiper组件是第三方组件 所以在使用之前应该先在命令行安装,然后将第三方的模块引入(第三方模块地址:https://github.com/leecade/react-native-swipe ...

  8. React Native布局实践:开发京东client首页(三)——轮播图的实现

    上篇文章中,我们一起构建了京东client的TabBar.在本文中.将继续向大家介绍京东client首页轮播图及其下发功能button的开发方法,如今就让我们開始吧! 1.相关控件调研 眼下在Gith ...

  9. 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

    一.组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML.CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成. ...

随机推荐

  1. mysql想要别人远程能连接

    mysql -u root -pvmware mysql>use mysql; mysql>update user set host = '%' where user = 'root'; ...

  2. 关于对For循环嵌套优化的问题

    1.案例描述 由于一次Java面试的笔试题,当时没有写出很好的解决方案,特此专门撰写一篇博客来加以记录,方便日后的查看 面试题目如下:从性能上优化如下代码并说明优化理由? for (int i = 0 ...

  3. mysql 基础 增删改查语句

    MySQL:众多关系型数据库中的一种仓库 --数据库箱子 --表数据库:进入mysql 命令行: mysql -uroot -p查看所有数据库: show databases;创建数据库: creat ...

  4. "高大上" 名词整理

    大家在和朋友,同行交流时有没有经常遇到各种 "高大上" 的术语,很多词有没有把各位 “鸟哥” 们搞得一头雾水,现在我就把这些 "牛逼" 的东东都罗列一下, 大家 ...

  5. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  6. [No00009C]Visual Studio在 解决方案资源管理器 里同步定位打开的文件

    标题的意思就是在使用VS的时候,需要我们打开编辑的文件跟解决方案的资源管理器同步显示,这样方便定位到我们在修改哪个文件. 设置如下: 工具——选项——项目和解决方案——在解决方案资源管理器中跟踪活动项 ...

  7. 【repost】JavaScript Scoping and Hoisting

    JavaScript Scoping and Hoisting Do you know what value will be alerted if the following is executed ...

  8. 分布式监控系统Zabbix-3.0.3-完整安装记录(7)-使用percona监控MySQL

    前面已经介绍了分布式监控系统Zabbix-3.0.3-完整安装记录(2)-添加mysql监控,但是没有提供可以直接使用的Key,太过简陋,监控效果不佳.要想更加仔细的监控Mysql,业内同学们都会选择 ...

  9. Batis-iBatis基本操作(增删改查)

    Batis-iBatis基本操作(增删改查) 时间 2014-04-10 17:55:20  CSDN博客 原文  http://blog.csdn.net/mazhaojuan/article/de ...

  10. SQL操作符

    Oracle中的操作符算术操作符:无论是在sqlserver,或者是java中,每种语言它都有算术操作符,大同小异. Oracle中算术操作符(+)(-)(*)(/) 值得注意的是:/ 在oracle ...