五,項目實戰,頁面骨架開發
1. 組建拆封
-
static
目錄下加入文件css/reset.css
,做css格式的重置http://cssreset.com。 - 更改
index.html
,引入reset.css
, 加入meta 視口。
<meta name="viewport"
content = "width=device-width, initial-scale=1.0, maximum-scale=1.0,
minimum-scale=1.0, user-scalable=no">
<link rel="stylesheet" type="text/css" href="static/css/reset.css">
- 更改eslint語法。在
eslintrc.js
的rules下面加兩個配置:
'semi': ['error', 'always'],
'indent': 0
-
main.js
中new Vue({ el: 'body', components: { App } });
將body作為一個element掛載點,所以app.vue中寫的template代碼都在body標簽里面。
(Vue2.0中,不要把掛載點設置到 html 或者 body 標簽上,因為 Vue 2.0 現在會把組件的 dom 替換到掛載的節點上。所以你需要創建一個子節點,然后掛載上去。)
-
App.vue
中引入組件header并注冊。注意我們已經在webpack中寫過alias路徑,也可以不需要./
直接寫components
;components中的key不要命名為header,防止警告和原生標簽沖突。
import header from './components/header/header.vue';
export default {
components: {
'v-header': header
}
};
- 安裝stylus依賴。方法一,
cnpm install stylus stylus-loader
; 方法二,在package.json
里面改,然后cnpm install
。stylus語法參考張鑫旭的翻譯。
補充一點npm知識:
當你為你的模塊安裝一個依賴模塊時,正常情況下你得先安裝他們,在模塊根目錄下npm install module-name,然后連同版本號手動將他們添加到模塊配置文件package.json中的依賴里(dependencies)。
-save
和save-dev
可以省掉你手動修改package.json文件的步驟。
npm install module-name -save
自動把模塊和版本號添加到dependencies部分。
npm install module-name -save-dev
自動把模塊和版本號添加到devdependencies部分。
devDependencies 下列出的模塊,是我們開發時用的,不會被部署到生產環境,比如css-loader。dependencies 下的模塊,則是我們生產環境中需要的依賴。
- 在App.vue中引用header組件
<v-header></v-header>
;書寫tab布局的樣式和模板,使用flex布局(推薦阮一峰教程)。
注意我們不需要額外考慮瀏覽器兼容的style樣式,因為在 vue-loader/postcss
文件可以搞定。不過要注意兼容情況,參考這個http://coding.imooc.com/learn/questiondetail/3644.html
postcss根據http://caniuse.com/書寫,兼容性不錯。
<style lang="stylus" rel="stylesheet/stylus">
#app
.tab
display: flex
width: 100%
height: 40px;
line-height: 40px
.tab-item
flex: 1
text-align: center
</style>
- Vue-router
1.0的文檔在這里https://github.com/vuejs/vue-router/tree/1.0/docs/zh-cn
遵循課程,我們安裝0.7.13版本的vue-router,用npm安裝方法同上(package.json中要寫在dependencies里面)。
在main.js
中引用vue-router,按照官方文檔的例子來,要用extend語法加start掛載點,不能用new語法。注意app的寫法也要變。
components/goods/good.vue
(注意import的時候可以不需要.vue后綴)
<template>
<div>I am goods</div>
</template>
<script type="text/ecmascript-6">
export default {};
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App';
import goods from 'components/goods/goods';
import ratings from 'components/ratings/ratings';
import seller from 'components/seller/seller';
Vue.use(VueRouter);
let app = Vue.extend(App);
let router = new VueRouter();
router.map({
'/goods': {
component: goods
},
'/ratings': {
component: ratings
},
'/seller': {
component: seller
}
});
router.start(app, '#app');
App.vue
<template>
<div>
<v-header></v-header>
<div class="tab">
<div class="tab-item">
<a v-link="{ path: '/goods' }">商品</a>
</div>
<div class="tab-item">
<a v-link="{ path: '/ratings' }">評論</a>
</div>
<div class="tab-item">
<a v-link="{ path: '/seller' }">商家</a>
</div>
</div>
<router-view></router-view>
</div>
</template>
....
接著我們用router.go('/goods');
指定默認的路由。(vue-router 2.0 中,router.go 變成 router.push了 參數是一樣的.)
然后添加tab<a>標簽的stylus樣式。display改為塊級元素這樣點擊不用具體到文字上而是區塊上就可以。注意CSS書寫規范,先寫布局,方框等觸發dom重繪的放在布局后面,最后才寫字體、顏色等可以被繼承的。然后把默認的class名字v-link-active
換一個名字寫進new vuerouter中并添加樣式。
.tab-item
flex: 1
text-align: center
& > a
display: block
font-size: 14px
color: rgb(77, 85, 93)
&.active
color: rgb(240,20,20)
let router = new VueRouter({
linkActiveClass: 'active'
});
幾個tips:
如果改的是非 src 文件夾下的代碼,比如改的 webpack 的配置文件,就需要重啟服務。
vue-router hash 模式的大致原理是根據修改 hash 值,觸發 hashChange,然后對應的 hash 去把 router-view 渲染成對應的組件,不會引發頁面的重載。
3. 像素border實現
關于tab欄下面的1像素的實現,即不管什么dpr值都是1像素(嚴格意義上的像素,不是css像素)。由于dpr問題不能直接代碼里寫1px。手機驗證用草料https://cli.im生成二維碼可以方便手機查看。
流程:偽元素+Y軸縮放。先利用了mixin書寫嵌入代碼中的1px代碼,即 偽元素相對于元素絕對定位后(偽元素是宿主元素的子元素),給偽元素1像素邊框。然后給tab的div元素添加新的class, 根據設備最小dpr進行scallY。這些代碼我們做成全局的以便將來重復使用。
注意:before 和 :after 這兩個偽元素,是在CSS2.1里新出現的。起初,偽元素的前綴使用的是單冒號語法,但隨著Web的進化,在CSS3的規范里,偽元素的語法被修改成使用雙冒號,成為::before & ::after – 這個樣子,用來跟“偽類(pseudo-classes)”區分開,(例如 :hover, :active, 等)。
Q: 為啥在main.js已經全局引入了 mixin.stylus,在組件里還要再次@import mixin.stylus呢?
A: 全局引入后會被編譯成全局的css代碼,但mixin中的stylus函數無法編譯成css,所以 其他組件用到stylus函數時無法從全局的css中找到,還要在組件中引入mixin.stylus 才能被編譯成完整的css。mixin實際上就是把引用的mixin定義的代碼替換到引入的位置,從stylus的編譯考慮,如果你使用了某個mixin定義的代碼而不去指定它引用的路徑,那么它是完全不知道從哪去查找這個mixin定義的。
關于retina像素等等很繞的概念有幾個鏈接闡釋的不錯:
https://www.w3cplus.com/css/towards-retina-web.html
http://coding.imooc.com/learn/questiondetail/8563.html
http://benweizhu.github.io/blog/2017/03/25/css-retina-image/
我的疑問,,這段代碼不是很懂http://coding.imooc.com/learn/questiondetail/21399.html
具體代碼如下:
//mixin.styl
border-1px($color)
position: relative
&::after
display: block
position: absolute
left: 0
bottom: 0
width: 100%
border-top: 1px solid $color
content: ' '
// base.styl
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
.border-1px-dpr
&::after
-webkit-transition: scaleY(0.7)
transform: scaleY(0.7)
@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
.border-1px-dpr
&::after
-webkit-transition: scaleY(0.5)
transform: scaleY(0.5)
// App.vue
...
<style lang="stylus" rel="stylesheet/stylus">
@import "common/stylus/mixin"
.tab
display: flex
width: 100%
height: 40px;
line-height: 40px
// border-bottom: 1px solid rgba(7, 17, 27, 0.1)
border-1px(rgba(7, 17, 27, 0.1))
...