html三级联动选择地址,React.js组建实现省市区选择三级联动

1899de951cac

省市区三级联动滚动选择器

一、HTML 模板

使用 React 的网页源码,结构大致如下。

ListView

// ** Our code goes here! **

上面代码有两个地方需要注意。首先,最后一个

其次,上面代码一共用了四个库: react.js 、react-dom.js 、babel.min.js 和zepto.js,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。Babel 内嵌了对 JSX 的支持。通过将 Babel 和 babel-sublime 包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。

二、ReactDOM.render()

ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

/**

* 渲染整个app

*/

ReactDOM.render(

,

document.getElementById('app')

);

三、组件

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。

注意,原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。

/**

* 整个应用

*/

var App = React.createClass({

getInitialState: function () { //初始化数据

return {data: []}

},

/**

* 城市选择回调,返回省市区的下标

*/

onAddressSelect: function (pIndex, cIndex, aIndex) {

var data = this.state.data;

var address = data[pIndex].name

+ data[pIndex].city[cIndex].name

+ data[pIndex].city[cIndex].area[aIndex];

console.log(" address: --->" + address)

this.address = address;

//与渲染无关的数据 直接存在this对象里 如果存在State里面会导致页面脏渲染,卡顿

},

onClick: function () {

var ans = '选择的地址:'+this.address;

alert(ans);

},

componentDidMount: function () {

var self = this;

$.get("http://ac-wiuh7w1y.clouddn.com/c4acc5d3bec3fb3216fa.json",

function (data) {

self.setState({data: data});

});

},

render: function () {

return (

点击获取城市

data={this.state.data}

onAddressSelect={this.onAddressSelect}//传进回调

/>

);

}

});

1899de951cac

点击按钮获取地址

复合组件:我们可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。如上,父组建创建完后,需要创建选择组建WheelDialog。当三个子列表被滚动或点击时触发 onDataChange回调函数,根据type判断滚动的是哪个列表。

/**

* 选择组件

*/

var WheelDialog = React.createClass({

getInitialState: function () {

return {

data: [],

pro: [],//省数组

city: [],//市数组

area: [],//区数组

pIndex: 0,//当前的省下标

cIndex: 0,//当前的市下标

aIndex: 0,//当前的区下标

}

},

componentWillReceiveProps: function (nextProps) {

this.setState({data: nextProps.data});//把新的数据填进列表,setState会自动触发render更新界面

this.initData(nextProps.data);

},

initData: function (data) {

var pArr = [];

var cArr = [];

var aArr = [];

data.map(function (pro) {

pArr.push(pro.name);

});

if (data[0])

data[0].city.map(function (city) {

cArr.push(city.name)

});

aArr = data[0].city[0].area;

this.setState({

pro: pArr,

city: cArr,

area: aArr

});

this.props.onAddressSelect(0, 0, 0);

},

onDataChange: function (type, index) {

console.log(type + " --->" + index)

var cArr = [];

var aArr = [];

switch (type) {

case "pro"://省带动市区变化

this.state.data[index].city.map(function (city) {

cArr.push(city.name)

});

aArr = this.state.data[index].city[0].area;

this.setState({

city: cArr,

area: aArr,

pIndex: index,

cIndex: 0,

aIndex: 0,

});

break;

case "city"://市带动区变化

aArr = this.state.data[this.state.pIndex].city[index].area;

this.setState({

area: aArr,

cIndex: index,

aIndex: 0,

});

break;

case "area":

this.setState({aIndex: index});

break;

}

this.props.onAddressSelect(this.state.pIndex, this.state.cIndex, this.state.aIndex);//数据变化之后,触发回调

},

render: function () {

return (

index={this.state.pIndex}

onDataChange={this.onDataChange}/>

index={this.state.cIndex}

onDataChange={this.onDataChange}/>

index={this.state.aIndex}

onDataChange={this.onDataChange}/>

);

}

});

单个滚动的列表组建,需要添加监听滚动事件,点击滚动事件,动画过渡事件。监听事件通过touch mouse Scroll三个事件来判断是否滚动结束。

/**

* 滚动组件

*/

var WheelView = React.createClass({

getInitialState: function () {

return {

data: []

}

},

/**

* 当有新的属性需要更新时。也就是网络数据回来之后

* @param nextProps

*/

componentWillReceiveProps: function (nextProps) {//接收父组建的数据

this.setState({

data: nextProps.data,

});//把新的数据填进列表,setState会自动触发render更新界面

this.refs.scroller.scrollTop = 40 * nextProps.index;

//每个列表选项高度为40px;

},

componentDidMount: function () {

var self = this;

self.refs.scroller.addEventListener('touchstart', touchStart, false);

self.refs.scroller.addEventListener('touchend', touchEnd, false);

self.refs.scroller.addEventListener('mousedown', touchStart, false);

self.refs.scroller.addEventListener('mouseup', touchEnd, false);

function touchStart(event) {

self.isTouchStart = true;

}

function touchEnd(event) {

self.isTouchStart = false;

self.timer = setTimeout(self.reSet, 100)

//100毫秒未触摸,认定滚动结束进行状态修正

}

},

/**

* 监听滚动事件

* @param e

*/

onScroll: function () {

var self = this;

if (this.timer) clearTimeout(this.timer)//如果一直在滚动,不会触发timer

this.timer = setTimeout(self.reSet, 100)

//100毫秒未滚动,认定滚动结束

},

/**

* 状态修正

*/

reSet: function () {

var self = this;

if (self.isTouchStart)return;//如果在触摸状态,返回

console.log('scrolling ends..')

var top = self.refs.scroller.scrollTop;//滚过的高度

var dis = top % 40;

var target;

if (dis > 20) {//超过一半,向下滚

target=top + (40 - dis);

self.transfrom(target);

} else {//否则滚回去

target=top - dis;

self.transfrom(target);

}

self.index = target / 40;// 当前选中的序号

self.props.onDataChange(self.props.type, self.index);

},

handleClick:function(e){ //点到哪个滚到目标位置

console.log(e.clientY-120);

var distance = e.clientY-120; //当前点击的位置距目标位置的距离

var self=this;

var top = self.refs.scroller.scrollTop; //滚过的高度

var target = top+Math.floor(distance/40)*40; //需要滚动的高度

self.transfrom(target); //动画过渡到目标位置

self.index = target / 40; // 当前选中的序号

self.props.onDataChange(self.props.type, self.index);

//回调函数数据改变事件

},

/**

* 动画过渡到目标位置

* @param target

*/

transfrom: function (target) {

var self = this;

var now = self.refs.scroller.scrollTop;

var step = (target - now) / 20;

setTimeout(function () {

self.refs.scroller.scrollTop = self.refs.scroller.scrollTop + step;

if (self.refs.scroller.scrollTop != target)

setTimeout(this, 10);//没有滚动到目标位置,继续触发自己

},10);

},

render: function () {

return (

ref="scroller"

onScroll={this.onScroll}

onClick={this.handleClick}>

{

this.state.data.map(function (item) {

//循环把数据显示出来

return

{item}

})

}

);

}

});

最后,添加自己喜欢外部样式。。。

#app{

width:450px;

height:250px;

margin:0 auto;

padding:0 25px;

}

.container {

height: 200px;

width: 150px;

float: left;

overflow: scroll;

}

.scroller {

padding-top: 80px;

padding-bottom: 80px;

}

.item {

height: 40px;

text-align:center;

line-height: 40px;

cursor:pointer;

}

::-webkit-scrollbar { /*隐藏滚轮*/

display: none;

}

.box {

width: 450px;

height: 40px;

position: absolute;

z-index: 1;

top: 80px;

border: dashed 1px #f00;

}

.dialog {

position: relative;

width:452px;

height:200px;

border:1px solid #eee;

/*background: #ff0;*/

box-shadow: 5px 5px 5px #ddd;

}

.btn {

width:200px;

color:white;

text-align: center;

border-radius: 5px;

background: red;

margin: 10px auto;

border: solid 1px red;

cursor:pointer;

}

OK!简单的省市区三级联动就完成啦。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值