其實你也可以,甚至做得更好...
首先看一下效果:用vue2.0實現SPA:模擬ios7操作 與 通訊錄實現
github地址是:https://github.com/QRL909109/ios7 如果您覺得可以,麻煩給一個star,支持我一下。
之前接觸過Angular1.0,React,都只是學點入門,但對於Vue卻覺得很容易上手,不止入門簡單,插件也是很豐富的,腳手架也是便利的很...
項目分析:
1.首屏滑動解鎖,並能移動小圓點
2.主屏幕 長按圖標抖動,刪除圖標,點擊小圓點的主屏幕 抖動停止
3.點擊電話圖標,進入電話模塊
4.進入個人中心:點擊編輯,移入刪除圖標,滑動出現刪除;點擊完成,刪除圖標消失
5.進入通訊錄:右側固定欄滑動 列表滑動到相應位置(使用better-scroll 插件)
6.進入撥號:撥號與刪除
插件介紹:
vue-router: vue路由插件 vue-router 2.0 中文文檔
vuex: vue狀態管理 vuex 1.0 中文文檔 方便組件共用狀態
better-scroll: 優化滑動性能的插件
lib-flexible: 手淘移動端H5 終端適配
moment: 時間格式化插件
項目布局:
采用手淘的flexible 這里有學習資源 使用Flexible實現手淘H5頁面的終端適配
要點:
1.根據手機dpr設置不同的scale,font-size (注意ios的dpr會適應變化,而Android的dpr一直為1)
2.整個屏幕寬度默認為10rem,采用750設計稿上下兼容,1rem = 75px
3.文字用px寫,分別寫出兼容
div{ font-size:12px; } [data-dpr="2"]{ font-size:24px; } [data-dpr="3"]{ font-size:36px; }
4.采用flex彈性布局(注意兼容高低版本)
開始:(挑有用重點講)
1、修改webpack.base.conf.js
利用webpack alias定義別名,方便輸入路徑,根據完整絕對地址
例如:
resolve: { extensions: ['', '.js', '.vue'], fallback: [path.join(__dirname, '../node_modules')], alias: { 'vue$': 'vue/dist/vue', 'src': path.resolve(__dirname, '../src'), 'assets': path.resolve(__dirname, '../src/assets'), 'components': path.resolve(__dirname, '../src/components'), 'store':path.resolve(__dirname,'../src/vuex/store'), 'getters':path.resolve(__dirname,'../src/vuex/getters'), 'actions':path.resolve(__dirname,'../src/vuex/actions'), 'mock':path.resolve(__dirname,'../src/mock') } },
這樣只要在任意位置使用 import ... from actions
webpack將會自動匹配actions的位置,不用再去計算文件位置,寫出'../../../actions'。
2、配置路由:在src目錄下新建 route-config.js
const routes=[ { path: '/main', name: 'main', meta: { title: '主頁面' }, component: resolve => { require(['./views/main.vue'], resolve) }, children: [ { path: '', name: 'personal', meta: { title: '個人收藏' }, component: resolve => { require(['./views/phone/personal.vue'], resolve) }, children:[ phone_detail ] } ] },{ .... },{ path: '*', redirect: { name: 'main' } } ]; export default routes
這里采用異步組件,按需加載,使用webpack的代碼分割功能。
路由機制是采用匹配規則,根據path匹配URL的路徑,從而加載對應的組件。
這里稍微提一下vue-router 1.0 和 vue-router 2.0 寫法的區別
vue-router1.0
傳遞vue-router實例,通過map進行定義路由映射
vue-router2.0
使用router 構造配置 routes
tips: 設置標題欄的title
通過vue-router實例后的afterEach,to能獲取每個路由的狀態,這時候便能使用document.title = to.meta.title (前提是router-config 里面有設置meta對象)
3、APP.vue結構
考慮到小圓點是所有頁面都存在的,所以結構為router-view加載路由匹配頁面,另外加載小圓點組件。
<template> <div class="_full"> <!-- app router --> <transition name="bounce"> <keep-alive> <router-view></router-view> </keep-alive> </transition> <!--小圓點--> <topPoint></topPoint> </div> </template>
或許你有疑惑 keep-alive 加在這有什么用?
keep-alive 會緩存不活動的組件實例,而不是銷毀它們。主要用於保留組件狀態或避免重新渲染
在做“個人收藏”模塊遇到很詭異的bug (沒加 keep-alive)
剛開始能刪除數據,但跳轉到其他頁面重新回來后,就不能執行刪除了。
后面一分析才知道,在從其他頁面跳轉回來后,組件重新渲染,再次請求了列表數據,而頁面的數據卻緩存着,導致數據不一致。加入keep-alive就能保留組件狀態
4、v-touch不兼容vue2.0解決方案
本以為應該會有插件支持的,結果沒法找到,只能自己寫簡單指令識別下。(只支持長按 press,向上 swipeup,向下 swipedown,向左swipeleft,向右 swiperight)
使用 v-touch:swiperight="methodFunc"
vue指令 touch 使用bind,
- binding.arg 獲得傳入模式
- el 監聽綁定的事件
- binding.value 獲得傳入的事件
通過對touchstart touchmove touchend 的判斷,執行對應的事件。
5、引入better-scroll插件
功能:優化滾動,能模仿像原生彈性的效果
使用:需要在外部包含固定高度的容器
<div ref="scrollWrapper"> <ul> <li v-for="item in List" class="commit-hook"></li>
</ul> </div> <script> import BScroll from 'better-scroll' export default{ created(){ this.$nextTick(() => { //這里需要異步 this._initScroll(); }) }, methods: { _initScroll(){ this.containerScroll = new BScroll(this.$refs.scrollWrapper,{ click:true //可點擊 }); } } } </script>
這樣將會添加translate,使用貝塞爾曲線,達到原生效果。
如果需要實時知道滾動的區域,可以這么配置:
created(){ this.$nextTick(() => { this._initScroll(); this._calculateHeight() }) }, methods:{ _initScroll(){ this.containerScroll = new BScroll(this.$refs.scrollWrapper, { probeType: 3 }); this.containerScroll.on('scroll', (pos)=> { this.scrollY = Math.abs(Math.round(pos.y)); //實時獲取Y軸的數值 }) } _calculateHeight(){ let commitList = this.$refs.commitBox.getElementsByClassName('commit-hook'); //獲取對應的DOM元素 let height = 0; this.listHeight.push(height) for (let i = 0; i < commitList.length; i++) { let item = commitList[i] height += item.clientHeight; this.listHeight.push(height) } } } computed: { currentIndex(){ //實時獲得當前的區域 for (let i = 0; i < this.listHeight.length; i++) { let height1 = this.listHeight[i]; let height2 = this.listHeight[i + 1]; if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { return i; } } return 0; } }
通過對比 v-for的 index 與 currentIndex 就能實時知道位置了。
6、組件間的通信
可以看看我的另一篇文章 vue2.0--組件通信(非vuex法)
主要用到父子 子父 通信方法,但為了方便項目使用 vuex狀態管理。
以上的項目很基礎,練習一遍,便能比我做的更好... 如有缺漏,做不好的地方,歡迎大家指正討論。
如果您覺得有幫助,請star一下,給予我更好的支持。
github地址是:https://github.com/QRL909109/ios7
如需轉載,請注明出處。