整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          HTML5實戰(zhàn)-簽到功能

          篇文章講到HTML炫酷的主流框架,今天小明就介紹一個HTML5功能的實現(xiàn)代碼

          Introduce(介紹)

          用戶簽到的H5例子(css+jquery,無圖片),由于網上找的的用戶簽到例子都不好,要不就是好多圖片組成的,要不就大量冗余代碼,所以特意做了個簽到界面(移動端)。

          User sign sample page for mobile using h5 which only use css + jquery + html.

          一些關鍵的地方

          這個功能的編寫思路是,先構建日期和簽到相關數(shù)據(jù),然后從服務端獲取數(shù)據(jù),并對原有數(shù)據(jù)進行更改,最后進行渲染。

          這樣子很好的擺脫了邏輯比較凌亂的問題,并且可以直接將這些數(shù)據(jù)用 vue.js 來掛載(本文沒有這樣做)。

          生成日期數(shù)據(jù)

          //生成日期數(shù)據(jù)
           function buildData() {
           var da = {
           dates: [],//日期數(shù)據(jù),從1號開始
           current: '',//當前日期
           monthFirst: 1,//獲取當月的1日等于星期幾
           month: 0,//當前月份
           days: 30,//當前月份共有多少天
           day: 0,//今天幾號了
           isSigned: false,//今天是否已經簽到
           signLastDays:3,//連續(xù)簽到日子
           signToday: function () {
           this.isSigned = true;
           this.dates[this.day].isSigned = true;
           },
           };
           var ds = [];
           //初始化日期數(shù)據(jù)
           var dt = new Date();
           da.current = dt.ToString('yyyy年M月d日');
           da.monthFirst = new Date(dt.getFullYear(), dt.getMonth(), 1).getDay();
           da.month = dt.getMonth() + 1;
           da.days = new Date(dt.getFullYear(), parseInt(da.month), 0).getDate();//獲取當前月的天數(shù)
           da.day = dt.getDate();
           for (var i = 1; i < da.days + 1; i++) {
           var o = {
           isSigned: false,//是否簽到了
           num: i,//日期
           isToday: i == da.day,//是否今天
           isPass: i < da.day,//時間已過去
           };
           ds[i] = o;
           }
           da.dates = ds;
           return da;
           }
          

          有了數(shù)據(jù)之后,就可以將數(shù)據(jù)轉換為界面了

          //渲染數(shù)據(jù)
           function renderData(da) {
           var signDays = document.getElementById('spSignDays');
           signDays.innerText = da.signLastDays;
           var root = document.getElementById("signTable");
           root.innerHTML = '';
           var tr, td;
           var st = da.monthFirst;
           var dates = da.dates;
           var rowcount = 0;
           //最多6行
           for (var i = 0; i < 42; i++) {
           if (i % 7 == 0) {
           //如果沒有日期了,中斷
           if (i > (st + da.days))
           break;
           tr = document.createElement('tr');
           tr.className = 'darkcolor trb';
           root.appendChild(tr);
           rowcount++;
           }
           //前面或后面的空白
           if (i < st || !dates[i - st + 1]) {
           td = document.createElement('td');
           td.innerHTML = '<div class="sign-blank"><span></span></div>';
           tr.appendChild(td);
           continue;
           }
           //填充數(shù)字部分
           var d = dates[i - st + 1];
           td = document.createElement('td');
           var tdcss = '';
           if (d.isToday)
           tdcss = 'sign-today';
           else if (d.isPass)
           tdcss = 'sign-pass';
           else
           tdcss = 'sign-future';
           if (d.isSigned) {
           tdcss = 'sign-signed ' + tdcss;
           td.innerHTML = '<div class="' + tdcss + '"><span>' + d.num + '</span><svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="sign-pin svg-triangle "><polygon points="0,0 35,0 0,35" /></svg></div>';
           } else {
           tdcss = 'sign-unsign ' + tdcss;
           td.innerHTML = '<div class="' + tdcss + '"><span>' + d.num + '</span></div>';
           }
           tr.appendChild(td);
           }
           //計算是否需要添加最后一行
           if ((st + da.days + 1) / 7 > rowcount)
           root.appendChild(tr);
           }
           //構建日期數(shù)據(jù)
           var da = buildData();
           //渲染
           renderData(da);
          

          以上就是本篇文章的全內容了

          學習從來不是一個人的事情,要有個相互監(jiān)督的伙伴,想要學習或交流前端問題的小伙伴可以私信回復小明“學習” 獲取資料,一起學習!

          于互聯(lián)網發(fā)展的今天,IT行業(yè)慢慢變成大多數(shù)年輕人發(fā)展的目標,不僅前景好,薪資也是越來越高的,而web前端是行業(yè)中需要的技術,也促進了大多數(shù)朋友在學習html5,今天小猿圈講師給你分享基于iview的router常用控制方式,在學的過程中不浪費時間少走彎路。

          1、iview的router控制需求

          最近在使用iview框架寫項目,遇到了一些路由控制上的問題,解決過程中也有一些心得,故在此記錄下來.

          每個項目在開發(fā)時,對于類似tags(標簽頁)的控制需求都不盡相同,故以下先列出本文所述項目對標簽頁的控制要求(如有不同需求,本文當也可提供一些思路):

          對于同名(name)的路由標簽頁,不能打開多個.譬如說從商品列表中打開商品展示標簽頁,如果已經有在打開的商品編輯頁面,則替換之.新打開的,未保存,已保存的標簽頁,同時只能存在一個(即不同params相同name的route只能有一個);

          替換掉一個新的頁面時,通過切換的方式切換回來(先切到其他標簽頁再切換回來),仍是原來頁面的內容(即實際記錄的params在替換后應變化).類似的情況,還應包含單據(jù)從未保存到已保存,以及保存并新增功能;

          2、基于vue的router控制

          iview是基于vue的框架,故vue本身自帶的router控制方法是必然可行的.

          vue變更路由的常用方式參考以下(該方法在官方api中有更詳細的介紹):

          //變更當前路由(有歷史記錄,建議使用此方式)

          this.$router.push({

          name:'routerName',

          params:routerParam

          })

          //變更當前路由(無歷史記錄)

          this.$router.replace({

          name:'routerName',

          routerParam

          })

          官方路由變更確實可以正常打開標簽頁,但在實現(xiàn)1中所提到的各種需求的時候,就有些不滿足需求了.為此,需要參考3中,如何基于iview的outer控制.

          3、基于iview的router控制

          iview在控制路由的時候,使用vuex中的app.js來記錄標簽頁路由信息,如果對vuex還是很了解的話,可以通過這篇博文來先打一下基礎.

          3.1如何實現(xiàn)需求1.1

          想要實現(xiàn)不同params相同name的route在iview中只能有一個,關鍵是改變iview對路由相等的判斷方法,即'/src/libs/util.js'里的routeEqual方法:

          /**

          * @description 根據(jù)name/params/query判斷兩個路由對象是否相等

          * @param {*} route1 路由對象

          * @param {*} route2 路由對象

          */

          export const routeEqual = (route1, route2) => {

          return route1.name === route2.name

          // 此處改變相同路由的判斷方式,改為name相同即認為相同

          // const params1 = route1.params || {}

          // const params2 = route2.params || {}

          // const query1 = route1.query || {}

          // const query2 = route2.query || {}

          // return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2)

          }

          這里稍微解釋下(如果不關注原因,可以直接看3.2).當改變路由時,'src\components\main\main.vue'作為近乎頂層的組件控制著近乎所有的全局邏輯,其中就有對路由的監(jiān)控:

          ...

          <side-menu

          accordion

          ref="sideMenu"

          :active-name="$route.name"

          :collapsed="collapsed"

          @on-select="turnToPage"

          :menu-list="menuList"

          >

          ...

          //此方法隸屬于methods,用以監(jiān)控side-menu的選擇事件,即平時從左側菜單打開標簽頁的邏輯

          turnToPage (route) {

          let { name, params, query } = {}

          if (typeof route === 'string') name = route

          else {

          name = route.name

          params = route.params

          query = route.query

          }

          if (name.indexOf('isTurnByHref_') > -1) {

          window.open(name.split('_')[1])

          return

          }

          this.$router.push({

          name,

          params,

          query

          })

          },

          ...

          watch: {

          // 檢測route的變化

          $route (newRoute) {

          const { name, query, params, meta } = newRoute

          this.addTag({

          route: { name, query, params, meta },

          type: 'push'

          })

          this.setBreadCrumb(newRoute)

          this.setTagNavList(getNewTagList(this.tagNavList, newRoute))

          this.$refs.sideMenu.updateOpenName(newRoute.name)

          }

          },

          ...

          從以上代碼可推測出,main.vue通過turnToPage方法實現(xiàn)打開標簽頁的邏輯,但方法內部并沒有體現(xiàn)便簽頁顯示效果變化(包含內部數(shù)據(jù)變化,以下同)的邏輯,這是由于顯示效果變化的邏輯,由對$router的監(jiān)控實現(xiàn).

          這樣,不止從左側菜單打開新標簽頁可以實現(xiàn)顯示變化效果,其他只要使用vue的原版push等方法改變router的方法,均可監(jiān)測到.

          逐步查看下各個方法,其中影響當前標簽頁顯示效果的,是'src/store/module/app.js'的addTag方法.

          addTag (state, { route, type = 'unshift' }) {

          let router = getRouteTitleHandled(route)

          if (!routeHasExist(state.tagNavList, router)) {

          if (type === 'push') state.tagNavList.push(router)

          else {

          if (router.name === homeName) state.tagNavList.unshift(router)

          else state.tagNavList.splice(1, 0, router)

          }

          setTagNavListInLocalstorage([...state.tagNavList])

          }

          },

          盡管方法內部仍調用了很多,其中一個很重要的判斷,就是routeHasExist(路由是否存在),這個方法也是判斷是否為相同標簽頁的一個關鍵節(jié)點(該方法同樣在util.js):

          /**

          * 判斷打開的標簽列表里是否已存在這個新添加的路由對象

          */

          export const routeHasExist = (tagNavList, routeItem) => {

          let len = tagNavList.length

          let res = false

          doCustomTimes(len, (index) => {

          if (routeEqual(tagNavList[index], routeItem)) res = true

          })

          return res

          }

          明顯可以看出,這個方法內調用routeEqual,就是用以判斷是否為相同路由的實際方法(當然是通過比較新路由與已有路由進行比較),如此,僅需改變routeEqual即可.

          以防萬一,全局搜索下調用這個routeEqual的所有方法,發(fā)現(xiàn)所有調用的地方再routeEqual在改變后不會出現(xiàn)新的問題.

          3.2如何實現(xiàn)需求1.2

          在進行3.1的操作后,問題得到了部分解決.余下的問題在于需求1.2沒有得到實現(xiàn)和解決.

          首先是,如何實現(xiàn)從列表中打開或新建的,替換原來的標簽頁,在來回切換后不會回到原來的標簽頁.只需在app.js中注冊改變標簽頁參數(shù)的方法:

          // 變更指定路由的參數(shù)

          changeTagParams (state, route) {

          let routeOldIndex = state.tagNavList.findIndex(m => routeEqual(m, route))

          if (routeOldIndex !== -1) {

          let routeOld = state.tagNavList[routeOldIndex]

          routeOld.params = route.params

          state.tagNavList.splice(routeOldIndex, 1, routeOld)

          setTagNavListInLocalstorage([...state.tagNavList])

          }

          },

          然后在main.vue中對$route的監(jiān)控最后引用即可.

          watch: {

          // 檢測route的變化

          $route (newRoute) {

          const { name, query, params, meta } = newRoute

          this.addTag({

          route: { name, query, params, meta },

          type: 'push'

          })

          this.setBreadCrumb(newRoute)

          this.setTagNavList(getNewTagList(this.tagNavList, newRoute))

          this.$refs.sideMenu.updateOpenName(newRoute.name)

          // 增加路由參數(shù)變更環(huán)節(jié)

          this.changeTagParams(newRoute)

          }

          },

          其次,如果出現(xiàn)像保存并新增,或者從未保存到已保存,這兩種情況來回切換后不會回到原來的情況.

          保存并新增,關鍵是"新增"效果:

          // 清空數(shù)據(jù),該方法在保存后調用

          clearData () {

          //該部分是用來清除當前route的參數(shù)

          this.$router.push({

          params: Object.assign(this.$route.params, { id: undefined })

          })

          //這部分代碼是用來清空當前頁面內容,每個模塊都不盡相同,不必模仿

          this.mOtherExpense = JSON.parse(JSON.stringify(this.mOtherExpenseInitial))

          this.tableData = [{}]

          this.loadCode()

          this.mOtherExpense.openingDate = new Date()

          },

          從未保存到已保存,關鍵同樣是如何讓route記住新的id(或其他參數(shù)):

          // 設置路由id,該方法在第一次保存后調用

          setData (id) {

          //這里的id是保存后從后臺傳來的新id

          this.$router.push({

          params: Object.assign(this.$route.params, { id })

          })

          }

          文中已將本人常用的iviewrouter控制方式提出,或有未涉及者,根據(jù)以下了解大概也可解決:

          app.js中的state.tagNavList是標簽頁中顯示的標簽集合;如果要改變一些內容,main.vue中對$route的監(jiān)控是事件發(fā)起的開端,可考慮從這里修改;

          以上就是小猿圈web前端講師對于基于iview的router常用控制方式的介紹,記住一定要練習,多學多看多練這才是學習一門新技術好的開始,如果沒有系統(tǒng)的視頻可以觀看小猿圈,里面有更完善更全的視頻。

          面是測試html5重力感應的demo

          http://bbs.qietu.com/html/zhongli/

          http://www.qietu.com/html/f2/qqqianbao/

          demo2是切圖網為騰訊網提供的web前端技術支持的項目,采用的就是html5的重力感應。

          重力感應主要用到兩種事件:

          1 orientationchange

          這個事件在屏幕發(fā)生翻轉時觸發(fā)

          window.orientation可獲得設備的方向,一共有三個值0:豎直, 90:右旋, -90:左旋

          2 deviceorientation 和 MozOrientation(firefox專用)

          deviceorientation事件可獲得三個值alpha,beta,gamma,分別代表繞Z軸的旋轉角度(0~360),繞X軸的旋轉角度(-180~180),繞Y軸的旋轉角度(-90~90)

          MozOrientation事件中可獲得三個值z,x,y,分別代表垂直加速度,左右的傾斜角度,前后的傾斜角度(取值范圍:-1~1)

          坐標系見下圖

          下面是示例游戲用到重力感應的代碼:

          1. window.onorientationchange = function(e){

          2. game.hideNavBar(); //屏幕翻轉時隱藏地址欄

          3. if(game.stage) game.stage.updatePosition(); //更新舞臺位置

          4. };

          5. window.ondeviceorientation = function(e)

          6. {

          7. var ang;

          8. var o = window.orientation; //獲取設備方向

          9. if(o == 90){

          10. ang = e.beta; //設備橫向1

          11. }

          12. else if(o == -90){

          13. ang = -e.beta; //設備橫向2

          14. }

          15. else if(o == 0){

          16. ang = e.gamma; //設備縱向

          17. }

          18. if(ang > 5)

          19. {

          20. keyState[Q.KEY.RIGHT] = true;

          21. }

          22. else if(ang < -5)

          23. {

          24. keyState[Q.KEY.LEFT] = true;

          25. }

          26. else

          27. {

          28. keyState[Q.KEY.RIGHT] = false;

          29. keyState[Q.KEY.LEFT] = false;

          30. }

          31. }

          無附件,源碼面前,了無秘密,作為web前端工程師,我們需要具備查看源碼的能力。

          原文:http://bbs.qietu.com/forum.php?mod=viewthread&tid=15036


          主站蜘蛛池模板: 无码aⅴ精品一区二区三区| 国产精品无码一区二区三级| 69福利视频一区二区| 国产精品第一区第27页| 狠狠色婷婷久久一区二区| 一区二区视频在线观看| 肉色超薄丝袜脚交一区二区| 成人免费一区二区三区| 国产成人一区二区三区高清| 亚洲av午夜福利精品一区| 亚洲av无码一区二区三区不卡| 国产精品视频第一区二区三区| 一区二区三区四区视频在线| 91在线视频一区| 国产精品一区三区| 人妻AV一区二区三区精品| 在线播放一区二区| 男人的天堂亚洲一区二区三区| 亚洲中文字幕无码一区二区三区| 精彩视频一区二区三区| 鲁大师成人一区二区三区| 国产精品视频一区国模私拍| 精品久久久久久无码中文字幕一区| 精品一区二区三区免费视频| 综合无码一区二区三区四区五区| 无码免费一区二区三区免费播放| 国产一区二区精品尤物| 久久综合一区二区无码| 亚洲熟女www一区二区三区| 亚洲一区二区三区AV无码| 一区二区福利视频| 国模吧无码一区二区三区| 丰满爆乳一区二区三区| 精品一区二区三区免费| 成人免费观看一区二区| 影院成人区精品一区二区婷婷丽春院影视| 亚洲av无码一区二区三区四区| 老熟妇高潮一区二区三区| 国产小仙女视频一区二区三区| 国产在线无码视频一区| 精品在线一区二区|