组件拆分

Posted Emily

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了组件拆分相关的知识,希望对你有一定的参考价值。

项目是基于组件化开发的思想,可以看做是在App.vue这个大组件内编写以下小组件:包括头部,中间导航区,以及最底下的内容区,使用vue-router来控制中间导航区(商品,商家,评价)页面的跳转。

 

1.先引入reset.css(文件路径:项目 -> static -> css)将标签默认样式进行设置,除了文件默认设置外,还会自定义一些标签样式,以保证后期项目更加美观的在手机上进行展现。文件下载地址:http://cssreset.com

reset.css文件中自定义部分:

 1 /* custom */
 2 a {
 3     color: #7e8c8d;
 4     text-decoration: none;
 5     -webkit-backface-visibility: hidden;
 6 }
 7 
 8 li {
 9     list-style: none;
10 }
11 
12 ::-webkit-scrollbar {
13     width: 5px;
14     height: 5px;
15 }
16 
17 ::-webkit-scrollbar-track-piece {
18     background-color: rgba(0, 0, 0, 0.2);
19     -webkit-border-radius: 6px;
20 }
21 
22 ::-webkit-scrollbar-thumb:vertical {
23     height: 5px;
24     background-color: rgba(125, 125, 125, 0.7);
25     -webkit-border-radius: 6px;
26 }
27 
28 ::-webkit-scrollbar-thumb:horizontal {
29     width: 5px;
30     background-color: rgba(125, 125, 125, 0.7);
31     -webkit-border-radius: 6px;
32 }
33 
34 html, body {
35     width: 100%;
36 }
37 
38 body {
39     -webkit-text-size-adjust: none;
40     -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
41 }
/* custom */

PS:css样式书写小技巧

像display、position这些会影响布局的样式写在前边
像height、weight这些会触发reload重绘的不可继承的样式写在中间
像字体、颜色等会触发reload重绘的可继承的样式写在最后

 

2.在 index.html 文件中引入 reset.css 文件,并进行理想视口的定义(宽度,初始缩放比,最大/小缩放比,是否允许缩放):

<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" href="static/css/reset.css">

 

3.eslint.js 文件:

例如:遇到关于分号的错误,因为默认 eslint 是默认不要分号的,如果要加分号,需要在 rules 中添加规则,详细配置规则可以在控制台报错中显示的网址进行查看:

\'semi\': [\'error\', \'always\'],
\'indent\': 0,
\'space-before-function-paren\': 0

 

4.main.js 文件:/* eslint-disable no-new */

js 中 new 一个对象后是需要赋值给某个值,但是 vue 实例化不需要,所以通过这条规则告诉 eslint 跳过对下面一行代码的规则校验,这样才不会报错。

 

5.vue模板设置:webstrome主菜单File -> setting -> Editor -> File and Code Templates -> 右侧‘添加 -> 填写Name,Extension,以及代码区(如下)。

 1 <template>
 2   
 3 </template>
 4 
 5 <script>
 6 
 7 </script>
 8 
 9 <style>
10 
11 </style>
vue模板代码

 

6.头部区块代码:在 src -> components -> header -> header.vue中添加代码,并将组件导出;在App.vue文件中引入 header 组件并注册,然后才可以使用header组件。

 1 <template>
 2   <div class="header">
 3     I am header
 4   </div>
 5 </template>
 6 
 7 <script type="text/ecmascript-6">
 8   export default {};
 9 </script>
10 
11 <style lang="stylus" rel="stylesheet/stylus">
12 
13 </style>
header.vue文件中代码

1   <div id="app">
2     <v-header></v-header>
3     <div class="tab">
4       I am tab
5     </div>
6     <div class="content">
7       I am content
8     </div>
9   </div>
App.vue中html代码
1 //  引用
2   import header from \'./components/header/header.vue\';
3 //  注册
4   export default {
5     components: {
6       \'v-header\': header
7     }
8   };
App.vue中js代码

PS:

1)因为使用的是 stylus 的语法,还需添加 stylus-loader 以及 stylus 组件库,否则会遇到:Module build failed: Error: Cannot find module \'stylus\' 这种报错信息。安装语法:npm install stylus-loader --save-dev 以及 npm install stylus --save-dev。

2)在 App.vue 文件中注册 header 组件时,变量名不能为 header ,因为和 html5 标签重复。

3)es6语法,注册组件时可以简写,如 header:header ,简写为 header。

 

7.导航区代码:

1)在 App.vue中添加导航区代码以及样式。导航区是水平排列,并且是三等分,可以使用移动端经典的布局:flex 布局。

1     <div class="tab">
2       <div class="tab-item">商品</div>
3       <div class="tab-item">评论</div>
4       <div class="tab-item">商家</div>
5     </div>
App.vue中导航区html代码
1   #app
2     .tab
3       display flex
4       width 100%
5       height 40px
6       line-height 40px
7       .tab-item
8         flex 1
9         text-align center
App.vue中导航区css代码

    

 

PS:

1)记得给 style 标签加上 lang 属性及 rel 属性,否则会因识别不了 stylus 而报错。

2)只需要写标准的 css 代码即可,vue-loader 可以解决 css 兼容性问题。(vue-loader 在 node-modules 文件夹里)

 

2)安装 vue-router 组件库,通过路由实现页面跳转。

用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,已经可以通过组合组件来组成应用程序,当要把 vue-router 添加进来时,需要将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。

vue-router官网文档:https://router.vuejs.org/zh-cn/essentials/getting-started.html

2-1)安装命令:npm install vue-router --save。

2-2)App.vue 文件中:使用 router-link 组件来进行商品、评价及商家这三个页面的导航,通过传入 `to` 属性指定链接,最后通过<router-view>将路由匹配到的组件渲染在内容区。

 1 <div id="app">
 2     <v-header></v-header>
 3     <div class="tab">
 4         <div class="tab-item">
 5           <!-- 使用 router-link 组件来导航. -->
 6           <!-- 通过传入 `to` 属性指定链接. -->
 7           <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
 8           <router-link to="/goods">商品</router-link>
 9         </div>
10         <div class="tab-item">
11           <router-link to="/ratings">评论</router-link>
12         </div>
13         <div class="tab-item">
14           <router-link to="/seller">商家</router-link>
15         </div>
16     </div>
17     <!--内容区-->
18     <div class="content">
19       <!-- 路由出口 -->
20       <!-- 路由匹配到的组件将渲染在这里 -->
21       <router-view></router-view>
22     </div>
23   </div>
App.vue中导航区html代码

2-3)goods,ratings,seller 组建的创建

在 components 文件夹中新建文件夹 goods,在 goods 文件夹新建文件 goods.vue,同理完成 ratings 和 seller 组件的创建。

以下是 goods.vue 代码内容,ratings.vue 和 seller.vue 同理。

   

2-4)main.js 文件中:

第一步:把 vue-router 的 export 值赋值给变量 VueRouter 。

第二步:如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter),这样才能成功安装路由功能。

第三步:定义(路由)组件。可以从其他文件 import 进来。(这里涉及文件别名设置知识点,具体可以看下面 PS 内容中第五点)

第四步:定义路由。每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者只是一个组件配置对象。

第五步:创建 router 实例,然后传 `routes` 配置。

第六步:创建和挂载根实例。记得要通过 router 配置参数注入路由,从而让整个应用都有路由功能。

第七步:使用 router.push 设置打开项目后默认显示商品页面。

 1 // The Vue build version to load with the `import` command
 2 // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
 3 import Vue from \'vue\';
 4 import App from \'./App\';
 5 import VueRouter from \'vue-router\';
 6 // 1. 定义(路由)组件.可以从其他文件 import 进来
 7 import goods from \'components/goods/goods\';
 8 import ratings from \'components/ratings/ratings\';
 9 import seller from \'components/seller/seller\';
10 
11 // 引入自定义的css样式
12 import \'common/stylus/index.styl\';
13 
14 // 0. 如果使用模块化机制编程,導入Vue和VueRouter,要调用 Vue.use(VueRouter)
15 Vue.use(VueRouter);
16 
17 Vue.config.productionTip = false;
18 
19 // 2. 定义路由
20 // 每个路由应该映射一个组件。 其中"component" 可以是
21 // 通过 Vue.extend() 创建的组件构造器,
22 // 或者,只是一个组件配置对象。
23 // 我们晚点再讨论嵌套路由。
24 const routes = [
25   {path: \'/goods\', component: goods},
26   {path: \'/ratings\', component: ratings},
27   {path: \'/seller\', component: seller}
28 ];
29 
30 // 3. 创建 router 实例,然后传 `routes` 配置
31 // 你还可以传别的配置参数, 不过先这么简单着吧。
32 const router = new VueRouter({
33   routes, // (缩写)相当于 routes: routes
34   linkActiveClass: \'active\'
35 });
36 
37 // 4. 创建和挂载根实例。
38 // 记得要通过 router 配置参数注入路由,
39 // 从而让整个应用都有路由功能
40 /* eslint-disable no-new */
41 new Vue({
42   el: \'#app\',
43   template: \'<App/>\',
44   components: {App},
45   router
46 });
47 // 现在,应用已经启动了!
48 
49 // 页面加载自动导航到goods页面
50 router.push(\'/goods\');
main.js

 

2-5)样式设置。

2-5-1)关于 active 的设置

在浏览器调试时,当点击商品、评论或者商家时,可以看到默认添加了一个名为 “router-link-active” 的类,这是vue-router 默认添加的,方便用户进行高亮等配置。可以直接在代码中对这个类名进行样式设置。如果觉得类名太长,可以在 vue-router 实例化进行选项配置,将默认类名改成自己想要的名称,比如将 “router-link-active” 改为 “active”。

2-5-2)1 像素边框的设置

问题背景:因为这是一个 webapp 应用,在手机端调试时会发现 1 像素边框有时候并不精确等于 1 像素,这是和手机的设备像素比(dpr) 有关。

设计思路:先在 .tab 上通过伪类 after,来增加一条下边框的线(写在 mixin.styl 文件中),再通过全局定义的 “border-1px”  这个类,根据手机 dpr 的不同对上边的伪类进行缩放(写在 base.styl 文件中),从而达到1 像素边框的设置。如果要设置上边框,就用伪类 before。

实现步骤:

第一步:在 mixin.styl 文件中完成 “border-1px” 的设置,在App.vue 中通过 @import 引入该文件,然后在 .tab 下使用该类。

第二步:在 base.styl 文件中完成 “border-1px” 的设置,在 index.styl 文件中加载所有样式文件,在main.js 中通过 @import 引入该文件。(这里涉及文件别名设置知识点,具体可以看下面 PS 内容中第五点)

第三步,在App.vue 中使用全局样式 “border-1px”。

注意:icol.styl 文件中有一些关于图标字体原路径的设置,因为路径变化,所以运行时可能会出错找不到文件。遇到这种情况修改一下文件中的路径就可以了。

关于样式设置部分具体顺序可见下图。

    

      

 1 border-1px($color)
 2   position relative
 3   // 进行伪类设置,一定要设置宽度,因为元素脱离了文档流
 4   &:after
 5     display block
 6     position absolute
 7     left 0
 8     bottom 0
 9     width 100%
10     border-top 1px solid $color
11     content \' \'
mixin.styl文件内容
 1 //为什么要写 -webkit :因为这里没有兼容性文件控制,所以要手写兼容性代码
 2 //本例需要的是1像素的边框,所以当dpr为1.5时,取0.7倍(1.5*0.7=1.05约等于1)。dpr为2时,取0.5倍(2*0.5=1)
 3 @madia (-webkit-min-device-pixel-ratio 1.5)
 4 (-min-device-pixel-ratio 1.5)
 5 .border-1px
 6   &::after
 7     -webkit-transform scaleY(0.7)
 8     transform scaleY(0.7)
 9 
10 @madia (-webkit-min-device-pixel-ratio 2)
11 (-min-device-pixel-ratio 2)
12 .border-1px
13   &::after
14     -webkit-transform scaleY(0.5)
15     transform scaleY(0.5)
base.styl文件内容
 1 <template>
 2   <div id="app">
 3     <v-header></v-header>
 4     <div class="tab border-1px">
 5       <div class="tab-item">
 6         <!-- 使用 router-link 组件来导航. -->
 7         <!-- 通过传入 `to` 属性指定链接. -->
 8         <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
 9         <router-link to="/goods">商品</router-link>
10       </div>
11       <div class="tab-item">
12         <router-link to="/ratings">评论</router-link>
13       </div>
14       <div class="tab-item">
15         <router-link to="/seller">商家</router-link>
16       </div>
17     </div>
18     <!--内容区-->
19     <div class="content">
20       <!-- 路由出口 -->
21       <!-- 路由匹配到的组件将渲染在这里 -->
22       <router-view></router-view>
23     </div>
24   </div>
25 
26 
27 </template>
28 
29 <script>
30   //  引用
31   import header from \'components/header/header.vue\';
32   //  注册
33   export default {
34     components: {
35       \'v-header\': header
36     }
37   };
38 </script>
39 
40 <style lang="stylus" rel="stylesheet/stylus">
41   @import "common/stylus/mixin.styl"
42   #app
43     .tab
44       display flex
45       width 100%
46       height 40px
47       line-height 40px
48       border-1px(rgba(7, 17, 27, 0.1))
49       .tab-item
50         flex 1
51         text-align center
52         /* &:表示父元素,即.tab-item */
53         & > a
54           /* 区块点击才能有反应 */
55           display block
56           font-size 14px
57           color rgb(77, 85, 93)
58           &.active
59             color rgb(240, 20, 20)
60 </style>
APP.vue