【总结】项目实践2016.12.20

项目总结【中东许愿池】

@(项目总结)[中东许愿池, 2016-12-20]

[TOC]

zencms的使用

  • <cms:custom></cms> 标签包裹需要配置的内容

    • name:这段文本的名称
    • fields:配置文案列
    • defaultRow:默认行数
    • row:最多行数
    • id:默认生成
  • 在结构中 <%=data%> 方式展示数据

<cms:custom name="表格" alias="alias" fields="name:实物奖品,pic:对应礼物,des:商品描述,num:星星数量" row="10"  defaultRow="1"  id="2809c7905e23fa827e53354b63e0d259">
	<% data.forEach(function(item, index){ %>
		<dd>
			<p class="name"><%=item.name%></p>
			<p class="pic">
				<img src="<%=item.pic%>" />
				<em><%=item.des%></em>
			</p>
			<p class="num"><%=item.num%></p>
		</dd>
	<%})%>
</cms>
  • 对应后台编译效果 后台效果图

多语言的使用

可配置多语言key、替换逻辑中固定名称、支持标签在多语言中的运用

使用前的配置
  • 在逻辑代码中lang.template('需要翻译的文案') 代替需要翻译的文案
  • 运用 zenbone lang key 命令 key 文件
  • google doc 中添加 key 值和需要翻译语言码
  • 点击菜单:File->Publish to the web发布文件
  • 选中 Published content & settings 配置:Automatically republish when changes are made。 每次变更都会自动发布文件,更新文件内容。
  • package.json 文件中配置 googleSpreadsheetId(Google Spreadsheet Id)和 googleSpreadsheetIndex(Google Spreadsheet中sheet的索引)
  • 使用 zenbone lang file 命令生成翻译文件
  • 将翻译文件复制到对应的多语言包中
字符串的使用
  • 调用 lang.template('需要翻译的文案')
翻译中有需要替换的内容
  • 调用 {lang.template('Up号: <%=code%>', { code: data.upliveCode})}
翻译中插入标签
  • 调用 <ul className="rule" dangerouslySetInnerHTML={{__html: lang.template('活动规则')}}></ul>

  • Google doc 中的配置

Google doc 配置示意

Google doc 配置示意2

  • package.json 文件中配置
"googleSpreadsheetId": "1EBZIWdCrGVmtxfxdvdETWnmlwpghPe1o1FbZjdnE4AU",
  "googleSpreadsheetIndex": 0,
  • 普通字段调用
<p>{lang.template('活动时间')}</p>
  • 可替换一部分内容调用
<span className="uplivecode">
	{lang.template('Up号: <%=code%>', { code: data.upliveCode})}
</span>
/********lang文件中这样设置*********/
'Up号: <%=code%>': 'Up賬號 : <%=code%>'
  • 带标签文本
<ul className="rule" dangerouslySetInnerHTML={{__html: lang.template('活动规则')}}></ul>

/************lang文件中这样设置***********/
"活动规则":"<li>活動規則</li>" + 
            "<li>1.在活動期間內總U幣高過十萬,且活動開始前已有U幣不高於九萬五。</li>" + 
            "<li>2.獎勵將在活動結束後聯絡到相關主播發放</li>"  + 
            "<li>3.活動數據會有延遲,依照官方時間為準。</li>",

项目总结2016-12-20

@(我的第一个笔记本)[十万主播项目得来][up-lakhanchor]

[TOC] @(万圣节活动项目得来)[2016-12-20, up-halloweenrank]

路由的使用

管理各个不用页面的跳转

  • 引用react-router 组件
import { Router, Route, hashHistory, useRouterHistory} from 'react-router';
import { createHashHistory } from 'history';
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
  • 渲染路由
    • path="url#后的页面名称"
    • component={对应模块名称}
render((
	    <Router history={appHistory}>
	        <Route path="/" component={Home}/>//没有任何参数是为Home模块
	        <Route path="/main" component={Main}/>//参数是main时为Main模块
	        <Route path="*" component={Home}/>//默认设置为Home模块(*--为其他所有的参数下)
	    </Router>
	), $('#wrap')[0]); 

配置全局信息

根据需求修改从服务器请来的参数做为全局属性在业务中使用

  1. 请求数据
  2. 截取请求数据中业务中需要的一段
  3. 改变请求数据中需要改变的数据
  4. 将改变后的数据付给新的全局数据
var getActivityInfo = function (){//请求数据
	let activityId = url.query('activityId');
    let promise = http.fetch({
        url: api.getActivityInfo(),
        data:{
             activityId
        }
    })
    return promise;
}
getActivityInfo().done((res)=>{

	let periodList = res.data.periodList.slice(1);  //获取请求数据中需要的一段

	window._global_periodList = periodList.map((item, index) =>{//将修改后的数据付给window._global_periodList,periodList为一个数组需要循环改变数组中的每一项
		let _lang = lang.getLangType();
		let activityTime;
		let dateStart,dateEnd;
		if (_lang == 'areg'){//更改需要的数据
			dateStart = formatData(item.startTime*1000, 'dd/MM HH:mm',12);
			dateEnd = formatData(item.endTime*1000, 'dd/MM HH:mm',12);
			activityTime = dateStart +'——' +dateEnd ;
		} else {
			dateStart = formatData(item.startTime*1000, 'MM月dd日 HH:mm');
			dateEnd = formatData(item.endTime*1000, 'MM月dd日 HH:mm');
			activityTime = dateStart +'——' +dateEnd ;
		}
		return {//返回一个对象,这个对象就是需要的数据
			title: lang.template('第' + (index + 1 )+ '天'),
            day: index + 1,
            startTime: item.startTime ,
            endTime: item.endTime ,
            activityTime: activityTime
		}
	});
})
  • 调用方式
console.log(global_periodList)
/**********显示数据*************/
[
	{
		title:第一天,
        day: 1,
        startTime:1408372402 ,
        endTime:14239789 ,
        activityTime: 10月28日 22:00——10月29日 21:59
	},
	{
		title:第二天,
        day: 2,
        startTime:1408376789 ,
        endTime:1423668999 ,
        activityTime: 10月29日 22:00——10月30日 21:59
	}
]

活动倒计时

从服务器获取每日开始、结束时间、当前时间戳,显示距离当天活动结束时间倒计时,tab默认选中当天。

设置当天为默认选中的第几天

在配置信息中填写对应数组 index+1 为第几天

  1. 设置默认选中为第一天
  2. 找出现在是第几天
    • 循环配置信息
    • 当前时间小于该项结束时间并且大于该项开始时间时设置项中的当前天数为选中状态
    • 如果当天超出整个活动天数设置最后一个为选中状态
      • 活动的最后天为位置信息中length-1的天数
距离每日活动结束倒计时
  1. 设置默认倒计时阈值false
  2. 计算当天还剩多少时间
    • 当天的结束时间戳 - 当前的时间戳
  3. 在有当天倒计时时间情况下将倒计时阈值开启true,并调用倒计时

  • 引用倒计时插件
 import Timer from './base/timer';
	constructor(props) {
        super(props);
        this.state = { //设置默认阈值
            isDisplayDaojishi: 0,
            currentDay: 1
        }
    } 
    
    getServerTime(serverTime){ //serverTime 从每个活动榜单接口中返回当前时间戳
        let self = this;
        let cutter;
        let activityEndTime;
        let activityInfo = _global_periodList;

        $.each(activityInfo, function(index , item){
            let startTime = item.startTime;
            let endTime = item.endTime;
            if (serverTime >= startTime && serverTime < endTime){//获取现在是活动的第几天
                cutter = endTime - serverTime;//计算当天距离活动还有多少时间
                self.setState({
                    currentDay: item.day//设置当前项中天数为默认选中的第几天
                });
                return false;
            }
        });
        
        activityEndTime = activityInfo[activityInfo.length-1]['endTime'];//最后一天的结束时间

        if(serverTime >= activityEndTime){//若活动已经结束最后一天做为当前选择天
            self.setState({
                    currentDay: activityInfo[activityInfo.length-1]['day']
                });
        }

        if (cutter) {//如果有当天倒计时时间开启倒计时阈值
            this.setState({
                isDisplayDaojishi: 1
            });
            self.daojishi(cutter);
        }
        loading.hide();
    }
    daojishi(cutter){ //调用倒计时插件
        
        var timer = new Timer({
            remainTime: cutter,
            // remainTime: 10,
            selector: {
                day: '#day',
                hour: '#hour',
                minute: '#minute',
                second: '#second'
            },
            isDoubleBit: true
        });

        timer.on('end', function() {})
    }
    render() {
        let daojishiDom;

        if (this.state.isDisplayDaojishi) { //倒计时阈值开启时显示倒计时
            daojishiDom = (
                <div className="daojishi">
                    <p className="daojishi-title">{lang.template("今日榜单活动结束还有")}</p>
                    <div className="daojishi-time"><em id="day">10</em>{lang.template("天")}<em id="hour"></em>{lang.template("小时")}<em id="minute"></em>{lang.template("分")}<em id="second"></em>{lang.template("秒")}</div>
                </div>
            );
        }
        return (
            <div className="carwar">   
                
                {daojishiDom}
                <div className="daily-billboard">
                    <DailyBillboard ref="dailyBillboard" tabs={_global_periodList} getServerTime={this.getServerTime.bind(this)} currentDay={this.state.currentDay} getActivityInfo={this.state.getActivityInfo}/>
                </div>
            </div>
        );
    }

显示全部数据中的某一部分

请求回来的数据只显示前10名,前三名和4-10的UI不用。若全部数据多于10只显示9条,最后显示点击查看更多

只取所有数据中的前十个
  • 请求数据的 pageSize 设置为10(需要前几设成几)
从前十中分别截取1-3、4-10
  • dataArr.slice(0, 3)获取数组中的1-3项、dataArr.slice(3) 获取数组中第四项及以后
多余10条时显示更多
  • 判断数据长度,如果大于需要显示的长度(10减3)list 中添加显示更多模块


loadData() { //请求数据
     let pageSize = this.props.maxSize + 1;//请求数据长度为需要的数据数
     let nextPage;
     let promise = http.fetch({
         url: api.getBillBoard(),
         data: {
             page: 1,
             pageCount: pageSize
         }
     });
     promise.done((res) => {
         if (res.code == 'SC_SUCCESS') {
             this.setState({
                 dataReady: true,
                 dataArr: res.data.hostList
             });
         }
     });
 }
render() { //渲染
   let $list;
   let dataArr = this.state.dataArr;
   let top3Arr = dataArr.slice(0, 3);//截取1-3的数据
   let top4to10Arr = dataArr.slice(3);//截取3以后的数据

   $list = (
       <div>
           <div className="top3">//1-3的渲染
               <Top3 list={top3Arr}/>
           </div>
           <div className="top4to10">//3以后的渲染
               { top4to10Arr.length > 0 ? <Top4to10 list={top4to10Arr} maxSize={this.props.maxSize - 3}/>: null}
           </div>
       </div>
   );

	return (
	    <div className="board-list-wrapper">
	        <div className="board-list">
	            {$list}
	        </div>
	    </div>
	);
}
  • 4-10的模块(数据多于10时显示显示点击更多)

从父组件传入数据,且传入的数据不是一次性,会改变是需要调用 reactcomponentWillReceiveProps方法

constructor(props){
        super(props);

        this.state = {
            list: props.list//将从外面传进来的数据设置为list
        }
    }
componentWillReceiveProps(props) {//从父组件传入数据,且传入的数据不是一次性,会改变是需要调用componentWillReceiveProps方法
    this.setState({
        list: props.list
    });   
}
render(){
    let dataArr = this.state.list;
    let maxSize = this.props.maxSize;
    let $list = [];

    if (dataArr.length > maxSize) {//获得到的数据大于需求数据长度
        let arr  = dataArr.slice(0, maxSize);//截取对应数据

        $list = arr.map(function(item, index){
            return <UserItemOther key={item.uid} rank={index + 4} data={item}/>
        });
        
        $list.push (<MoreUserItem key="more"/>);//添加查看更多模块
    } else {//获得到的数据不大于需求数据长度
        $list = dataArr.map(function(item, index){
            return <UserItemOther key={item.uid} rank={index + 4} data={item}/>;
        });
    }
    
    return (
        <div className="top4to10-list">
            {$list}
        </div>
    );
}

tab防止其他选项卡下滑滚动

  • 根据点击当前选项,从父模块中传入 selectedIndex
  • selectedIndex 等于当前 index 时设置当前选项中的可滚动阈值为开
  • 当可滚动阈值为开开始调用下滑滚动事件

  • 父模块

    onSelect = (index, e)=>{ //将点击时数组的index设置成selectedIndex
        this.setState({
            selectedIndex: index
        });
    }
    render(){
        let self = this;
        let hostTabs = this.props.tabs;

        return (
            <div className="daily-list-wrapper">
                    <Tabs  onSelect={this.onSelect} >                            
      
                    {
                        hostTabs.map(function(tab, i){
                            let enable;
 /*
 *如果数组的索引值与selectedIndex的值相等说明现在展示的为当前选中的tab
 * 设置当前选中的tab中的enable为true,其他的为false
 */
							enable = (i == self.state.selectedIndex) ? true: false;                            
                            return (
                                <TabPanel key={i}>
                                    <DailyList scrollEnable={enable}/>
                                </TabPanel>
                            )
                        })
                    }
                    </Tabs>
                </div>
        );
    }
  • 子模块
scrollList(e){
        let self = this;
        let timer;

        $(window).on('scroll',function(){
            if (self.props.scrollEnable) {//当scrollEnable阈值为true时才执行下拉滑动事件
                timer && clearTimeout(timer);
                timer = setTimeout(function () {
                
                    if (self.dataOver || self.isLoad) {
                        return;
                    } else {
                        let  body = document.body, docElement = document.documentElement;
                        //700 在页面滑到底部前700px就可以加载,增加交互流畅性
                        if(body.scrollTop > docElement.offsetHeight - docElement.clientHeight - 700){
                            self.getData();
                        }
                    }
                } , 500);
            }
       })  
    }

tab

切换选择菜单的同时切换接口的请求地址

当需要清楚以前的dom,在更改为新dom
  • 设置一个阈值,当点击时setState将阈值关闭,在setState的回调中将阈值开启,并set相应的属性值
  • 在render时通过阈值和空div,清楚过去的dom,在setState时渲染新的dom
constructor(props) {
        super(props);
        this.state = {//设置tab需要的配置
           tab:[
                { 
                    name:lang.template('冲刺中'),
                    url:api.getStriveInfo()
                },
                { 
                    name:lang.template('已达成'),
                    url:api.getFinishInfo()
                }
           ],
           selectId:0,//设置默认参数
           url:api.getStriveInfo(),
           isMount:true//设置中间转态的阀门
        };
    }
    chooseTab =(index,url)=> {//点击tab是改变state对应的值
        this.setState({
             isMount: false//当setState时设置阀门为false
        }, function(){//setState后的回调
           this.setState({//setState成功后再打开阀门,设置对对应的属性值
                selectId:index,
                url:url,
                isMount: true
            }) 
        })
        
    }
    render() {
        let self = this;
        let $tab = [];
        
        this.state.tab.forEach(function(item,index){//渲染tab,并根据数组的index是否与selectId相等决定选中状态
            $tab.push(
                <i className={self.state.selectId == index ?item.style+ " checked":item.style}
                    key = {index}
                    onClick={self.chooseTab.bind(this,index,item.url)}
                >{item.name}</i>
            )
        })
  

        if(this.state.isMount) {//选中状态的阈值(react对比dom树)
            return (
                <div className="r-wrap">
                    <div className="banner">
                        <div className="bannerImg">
                            <p>{lang.template('活动时间')}</p>
                        </div>
                        <ul className="rule" dangerouslySetInnerHTML={{__html: lang.template('活动规则')}}></ul>
                        <ol className="award" dangerouslySetInnerHTML={{__html: lang.template('活动奖励')}}></ol>
                    </div>
                    <div className="rank">
                        <h1 className="tab">
                            {$tab}
                        </h1>
                        <List goProfile={self.goProfile} url={this.state.url}/>
                    </div>
                    <Refresh />
                </div>
            );
        } else { //切换tab时清楚上一个dom
            return <div></div>;
        }
        
    }


请求数据下拉加载更多

constructor(props) {
      super(props);
       this.state = {//加载、没有数据等情况需要显示在页面中的阈值
          list:[],
          page:1,
          url:this.props.url,
          dataLoading:true,
          empty:false,
          dataEnd:false
       };
       //防止异步请求时的阈值,只在逻辑代码中使用
       this.isLoading = true;
       this.dataOver = false;
   }
   componentDidMount(){//数据变更时调用下滑滚动事件
	 $(window).off('scroll');
   }
   componentWillUnmount() {//清楚滑滚动事件
     $(window).off('scroll');
   }
   getListInfo() {
        let self = this;
        let url = this.state.url;
        let page = this.state.page;//page每次都会有更改
        let pageSize = 25;      
        let promise = http.fetch({
            url: url,
            data:{
                index:page,
                pageCount:pageSize
            }
        });
        
        promise.done(function(res){

            if (res.code == 'SC_SUCCESS') {

                if (res.data.length < pageSize) {//当前页数组长度小于pageSize,说明是最后一页
                    self.dataOver = true;
                    self.setState({
                        dataLoading:false,
                        dataEnd:true
                    })
                } 
                if (page == 1) {
                    if (res.data.length == 0) {//当page==1时,数组长度为0,说明没有数据
                        self.setState({
                            empty:true,
                            dataLoading:false,
                            dataEnd:false
                        })
                    };
                };
                nextPage = page + 1;//请求一次过后将page增加1
                self.setState({
                    list:self.state.list.concat(res.data),//将每次请求过来的数据追加到数组中
                    page:nextPage//将新的page state到page
                }); 
                self.isLoading = false;  
            }
        });
        
    }
    scrollList(){
        let self = this;
        let page = this.state.page;
        let timer;
        $(window).off('scroll');
        $(window).on('scroll' , function () {
            timer && clearTimeout(timer);
            timer = setTimeout(function () {
                if (self.dataOver || self.isLoading) {//当没有数据或者正在 请求数据时,不执行下拉加载
                    return
                } else {
                    var body = document.body, docElement = document.documentElement;
                    // 700 在页面滑到底部前700px就可以加载,增加交互流畅性
                      if(body.scrollTop > docElement.offsetHeight - docElement.clientHeight - 700){

                            self.isLoading = true;
                            self.getListInfo();

                       }
                };
                
            } , 300);
        });
    }

更新列表

页码数设置为1,每页请求的长度为当前数据的长度


componentDidMount() {//数据变更时设置全局事件
    let self = this;
      $.channel.on('refreshAll', function(){
          self.refetch();
      });
  }
  componentWillUnmount() { //解绑全局事件
      $.channel.off('refreshAll');
  } 
 refetch() {
        let self = this;
        let pageSize = this.state.list.length;//请求数据长度为当前数据长度
        let promise = http.fetch({
            url: urls,
            data:{
                index:1,//请求第一页
                pageCount:pageSize
            }
        });

        promise.done(function(res){

            if (res.code == 'SC_SUCCESS') {
                self.setState({
                    list:self.state.list.concat(res.data)//将刷新请求过来的数据设置为渲染数据
                }); 
                self.isLoading = false;  
            }
        });
        
    }

@(2016.12.15)

从URL上获取具体参数

query(name, scope) {
	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"),
		scope = scope || 'search',
		r = location[scope].substr(1).match(reg);
	if (r != null) {
		return unescape(r[2]);
	}
	return null;
}
  • 调取方式
//url:www.baidu.com?sid=1
 var sid = query("sid");
 console.log(sid);// 1

获取平台类型

返回的平台类型: weixin, weibo, qq

	getPlatform() {
		let [ua, pl] = [navigator.userAgent, 'other'];

		if (ua.match(/micromessenger/i)) {
			pl = 'wechat';
		} else if (ua.match(/qq/i)) {
			pl = 'qq';
		} else if (ua.match(/weibo/i)) {
			pl = 'weibo';
		} 

		return pl;
	}
  • 调取方式:
//在微信中
    	platform = getPlatform();
    	console.log(platform) //weixi

获得客户端的版本号

让客户端在ua中添加对应字段和版本号(sfans)

getVersion() {
	var ua = navigator.userAgent;
	var reg = /sfans\/(.+?) /i;
	return reg.exec(ua)[1];
}
  • 调取方式
consoel.log(getVersion()) //sfans

获取当前系统类型

getSystem() {
    	let ua = navigator.userAgent;
    	return /(iPhone|iPad|iPod|iOS)/i.test(ua) ? 'ios' : /[aA]ndroid/i.test(ua) ? 'android' : 'pc';
}
  • 调取方式

      //在iOS中
      console.log(getSystem()) //ios
    

时间戳变为固定格式的日期

支持上下午

  • time:时间戳
  • pattern:时间格式
  • hourType:时间类型(12,24)
formatData =(time, pattern, hourType)=> {
        var dateObj = new Date(time);
        
        hourType = hourType || 24;

        if (!pattern) {
            pattern = "yyyy-MM-dd HH:mm:ss"; 
        }
        var val, result;
        var func = function(matched) {
            return matched.length == 2 && val < 10 ? ("0" + val) : val;
        };

        result = pattern.replace(/y{2,4}/, dateObj.getFullYear()); // the year
        val = dateObj.getMonth() + 1; // the month
        result = result.replace(/M{1,2}/, func);
        val = dateObj.getDate(); // the date
        result = result.replace(/d{1,2}/, func);
        
        if (hourType == 12) {
            val = dateObj.getHours(); // the hour
            let isAm = 1;

            if (val > 12) {
                result = result.replace(/H{1,2}/, function(matched){
                    if (matched.length == 2) {
                        if (val > 12) {
                            val = val - 12;
                            if (val < 10) {
                                val = '0' + val;
                            }
                            isAm = 0
                        } else if(val < 10){
                            val = '0' + val;
                            isAm = 1;
                        }
                    }
                    return val;
                });
                val = dateObj.getMinutes(); // the minute
                result = result.replace(/m{1,2}/, func);
                val = dateObj.getSeconds(); // the second
                result.replace(/s{1,2}/, func);
            } else {
                result = result.replace(/H{1,2}/, func);
                val = dateObj.getMinutes(); // the minute
                result = result.replace(/m{1,2}/, func);
                val = dateObj.getSeconds(); // the second
                result.replace(/s{1,2}/, func);
            }

            if( isAm ) {
                result +='am'
            } else {
                result +='pm';
            }
        } else {
            val = dateObj.getHours(); // the hour
            result = result.replace(/H{1,2}/, func);
            val = dateObj.getMinutes(); // the minute
            result = result.replace(/m{1,2}/, func);
            val = dateObj.getSeconds(); // the second
            result.replace(/s{1,2}/, func);
        }

        return result;
    }
  • 调取方式

      console.log(formatData(时间戳,'yyyy年MM月dd日 HH:mm',12))//2016年12月12日 12:12pm
    

图片轮播

引用SwipeSlide

class Banner extends Component {

    static defaultProps = {
        selectIndex: 0 // 默认第一项,索引值0
    }
    constructor(props) {
        super(props);
        
        let selectIndex = 0;
        
        if ('selectIndex' in props) { //插件中的当前图片索引
            selectIndex = props.selectIndex;
        } else {
            selectIndex = props.selectIndex;
        }

        this.state = {
            selectIndex: selectIndex //state当前图片索引
        };
    }
    componentDidMount(){
        let self = this;
        if (this.props.banner.length == 1) {
            $(".dot").hide();//一张图片是不显示圆点
        } else {
            this.timer = setTimeout(()=>{
                // 图片轮播插件调用 
				// $(this.refs.content)包含图片的大容器
                this.swipeSlide = new SwipeSlide($(this.refs.content), {
                    continuousScroll: true,
                    autoSwipe : true,
                    speed : 5000,
                    transitionType: 'ease-in',
                    callback: function(index){
                        self.setState({
                            selectIndex: index //回调后state索引
                        });
                    }
                });
     
            }, 500);
        };
    }
    render() {
        let self = this;
        let imgArr = this.props.banner;
        let $li = [],cls;

        return (
            <div className="banner-slide-wrap" ref="content" style={{opacity: this.state.opacity}}>
                    <ul className="slide-list">
                    {   
                        imgArr.map((item, i) => {  //循环渲染单张图片 容器
                            let cls = 'slide-item';
                            cls += this.state.selectIndex == i ? ' selected' : '';
                            return <li className='slide-item' key = {i} onClick={self.goBanner.bind(this,item.redirect)}><img src={item.images + '?imageView2/1/w/320/h/154'} /></li>
                        })
                    }
                    </ul>
                    <div className="slide-dots"> //圆点容器
                    {
                        imgArr.map((item, i) =>{
                            var cls = 'dot';
                            cls += this.state.selectIndex == i ? ' selected' : '';

                            return (
                                <span key={i} className={cls}></span>
                            );
                        })
                    }
                    </div>
                </div>
        ) 
    }
}

防止重复点击

列表中点击一个后其他所有按钮均不可重复点击

class List extends Component {
    constructor(props) {
        super(props);
        self.clicked = false ;//设置默认可点击状态(已点为false)
    }
    postTask = (item) => {//请求服务器接口
		let promise = $.ajax({
				url: urls,
				type: 'GET',
				data:{
					index:page,
					pageSize:25
				},
				dataType: 'json'
			});

			promise.done(function(res){

				if (res.code == 'SC_SUCCESS') {

					alert("成功")
				} else {
					alert("系统错误")
				} 
				 self.clicked = false;//获取数据成功设置回可点状态
			});
			promise.fail(function(res, type){
				self.clicked = false;//数据获取失败设置回可点状态
				alert("获取数据失败")
			}); 
    }
   
    
    goTask =(data)=> {
        let self = this;
        let platform = client.getPlatform();
      
        if (self.clicked || data.status == 1) {//当已点过状态或者已做任务状态不可点击
            return ;
        } else {
            self.clicked = true ;//点击进去以后设置为已点击过状态
        };   
    }
    render() {
        let self = this;
        return (
            <ul className="list" >
               <li onClick={self.goTask.bind(this,item)}></li>
            </ul>
        ) 
    }
}

在list 中修改其中一项的属性值

  • 数据机构:
	list:[
			{
				name:"aaa",
				status:0
			},
			{
				name:"bbb",
				status:0
			}
	]
  • 修改aaa的status为1
		list.forEach(function(data,i){
		   if ( data.name == "aaa" ) {
		          data.status = 1;
		      };
		  });
		  self.setState({
		      listInfo:list
		  })
```	  

* 修改后的数据变为

list:[
		{
			name:"aaa",
			status:1
		},
		{
			name:"bbb",
			status:0
		}
]

***

###PB文件的使用

>- 引入PB转化插件c-pbajax
>- 下载相应的PBJs编辑后的文件
>- 在HTML中引入种子文件

` 
 `

<script src="http://h.cdn.pengpengla.com/h5lib/3.0.0/js/protobuf.js></script>

/以上引入到HTML种子文件中/ import pbajax from 'c-pbajax';//引入统一的编译插件 import infoListpb from './pb/taskslistpb';//引入业务文件 import publicpb from './pb/publicpb';//引入说明文件 //https://star-service.pengpengla.com/t/tasks/act /*"package": "Banner.List",

  • "options": {
  • "objc_class_prefix": "BannerList",
    
  • "java_package": "com.asiainno.starfan.proto"
    

*/ }, pbajax.do( { service: 'sfanservice', //项目PB目录 api: '/t/tasks/act',//项目文件地址 header: { usertoken:_global_token//header中传入的参数 }, inchina: 1 }, new tasksactpb.Tasks.Act.Request({ //参数 version: vc, sid:sid, taskId:item.id }),
function(res){// success var dataWrap = publicpb.Result.decode(res), data; if (dataWrap.code == 1) { data = tasksactpb.Tasks.Act.Response.decode(dataWrap.data.value);//对应文件中的package console.log(item); } }, function(){}, function(){//服务器挂了 console.log("服务器挂了"); } );

----------

转载于:https://my.oschina.net/u/3047945/blog/806632

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值