在线商城项目02-展示商品列表页面并抽取公共组件
简介
本系列前期不过多关注样式,所以直接采用视频提供的重构。本篇主要进行如下工作:
- 展示商品列表页面
- 抽取公共组件
1. 展示商品列表页面
step1:新增存放重构资源的目录
视频提供的重构有点问题,大家可以使用我上传在github上的重构资源。
在根目录下新建一个resources文件夹,用来存放重构的资源文件。如果公司或者团队有专门的重构工程师,可以将这个文件夹交给他们管理。
如图,这里有红色和绿色,是因为有些文件我已经track了,而有的没有。使用webstorm你可以在新建文件的时候track,也可以自己过后手动track。我们打开goodsList.html,如下图:
step2:将重构页面资源引入src
在src下新增文件夹views,用来存放我们的页面文件。再在views下新建文件夹GoodsList,用来存放商品列表相关的文件。在GoodsList下新建一个GoodsList.vue文件。如图:
GoodsList.vue文件中放我们的重构内容:
<template>
<div>
<header class="header">
<div class="navbar">
<div class="navbar-left-container">
<a href="/">
<img class="navbar-brand-logo" src="../../assets/logo.png"></a>
</div>
<div class="navbar-right-container" style="display: flex;">
<div class="navbar-menu-container">
<!--<a href="/" class="navbar-link">我的账户</a>-->
<span class="navbar-link"></span>
<a href="javascript:void(0)" class="navbar-link">Login</a>
<a href="javascript:void(0)" class="navbar-link">Logout</a>
<div class="navbar-cart-container">
<span class="navbar-cart-count"></span>
<a class="navbar-link navbar-cart-link" href="/#/cart">
<svg class="navbar-cart-logo">
<symbol id="icon-cart" viewBox="0 0 38 32">
<title>cart</title>
<path class="path1"
d="M37.759 0h-4.133c-0.733 0.004-1.337 0.549-1.434 1.255l-0.546 4.342c-0.081 0.484-0.496 0.849-0.997 0.849-0.005 0-0.009-0-0.014-0h-27.604c-0.003 0-0.007-0-0.011-0-1.674 0-3.031 1.357-3.031 3.031 0 0.34 0.056 0.666 0.159 0.971l2.52 8.062c0.385 1.194 1.486 2.043 2.785 2.043 0.126 0 0.25-0.008 0.372-0.023l22.983 0.002c0.515 0.131 0.626 0.768 0.626 1.283 0.005 0.044 0.009 0.095 0.009 0.146 0 0.501-0.294 0.933-0.718 1.134l-22.439 0.003c-0.354 0-0.642 0.287-0.642 0.642s0.287 0.642 0.642 0.642h22.745l0.131-0.071c0.919-0.392 1.551-1.287 1.551-2.33 0-0.058-0.002-0.116-0.006-0.173 0.021-0.108 0.033-0.24 0.033-0.376 0-1.072-0.732-1.973-1.724-2.23l-23.357-0.004c-0.063 0.008-0.135 0.013-0.209 0.013-0.719 0-1.332-0.455-1.566-1.093l-2.53-8.095c-0.048-0.154-0.076-0.332-0.076-0.515 0-0.973 0.782-1.764 1.752-1.778h27.657c1.159-0.004 2.112-0.883 2.232-2.011l0.547-4.345c0.010-0.083 0.078-0.147 0.161-0.152l4.133-0c0.354 0 0.642-0.287 0.642-0.642s-0.287-0.642-0.642-0.642z"></path>
<path class="path2"
d="M31.323 9.69c-0.022-0.003-0.048-0.004-0.074-0.004-0.328 0-0.598 0.248-0.633 0.567l-0.809 7.268c-0.003 0.022-0.004 0.048-0.004 0.074 0 0.328 0.248 0.598 0.567 0.633l0.074 0c0.001 0 0.003 0 0.004 0 0.327 0 0.596-0.246 0.632-0.563l0.809-7.268c0.003-0.022 0.004-0.048 0.004-0.074 0-0.328-0.248-0.598-0.567-0.633z"></path>
<path class="path3"
d="M27.514 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM27.514 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
<path class="path4"
d="M9.599 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM9.599 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
</symbol>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-cart"></use>
</svg>
</a>
</div>
</div>
</div>
</div>
</header>
<div class="nav-breadcrumb-wrap">
<div class="container">
<nav class="nav-breadcrumb">
<a href="/">Home</a>
<span>Goods</span>
</nav>
</div>
</div>
<div class="accessory-result-page accessory-page">
<div class="container">
<div class="filter-nav">
<span class="sortby">Sort by:</span>
<a href="javascript:void(0)" class="default cur">Default</a>
<a href="javascript:void(0)" class="price">Price
<svg class="icon icon-arrow-short">
<use xlink:href="#icon-arrow-short"></use>
</svg>
</a>
<a href="javascript:void(0)" class="filterby stopPop">Filter by</a>
</div>
<div class="accessory-result">
<!-- filter -->
<div class="filter stopPop" id="filter">
<dl class="filter-price">
<dt>Price:</dt>
<dd><a href="javascript:void(0)">All</a></dd>
<dd>
<a href="javascript:void(0)">0 - 100</a>
</dd>
<dd>
<a href="javascript:void(0)">100 - 500</a>
</dd>
<dd>
<a href="javascript:void(0)">500 - 1000</a>
</dd>
<dd>
<a href="javascript:void(0)">1000 - 2000</a>
</dd>
</dl>
</div>
<!-- search result accessories list -->
<div class="accessory-list-wrap">
<div class="accessory-list col-4">
<ul>
<li>
<div class="pic">
<a href="#"><img src="../../../static/1.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">999</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/2.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">1000</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/3.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">500</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/4.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">2499</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="footer__wrap">
<div class="footer__secondary">
<div class="footer__inner">
<div class="footer__region">
<span>Region</span>
<select class="footer__region__select">
<option value="en-US">USA</option>
<option value="zh-CN">China</option>
<option value="in">India</option>
</select>
</div>
<div class="footer__secondary__nav">
<span>Copyright © 2017 IMooc All Rights Reserved.</span>
<a href="http://us.lemall.com/us/aboutUs.html">
About Us
</a>
<a href="http://us.lemall.com/us/termsofUse.html">
Terms & Conditions
</a>
<a href="http://us.lemall.com/us/privacyPolicy.html">
Privacy Policy
</a>
</div>
</div>
</div>
</div>
</footer>
</div>
</template>
<script>
export default {
data () {
return {}
}
}
</script>
这里需要注意两点:
- template下面要有一个root element,所以我们加了一层div
- 图片的引用地址改变了,我们将自己的logo.png替换assets下vue的logo,将产品图片文件放到static下。这里关于static和assets的不同可以看assets 和static的区别以及 webpack 模板的文档 - Handing Static Assets来了解。简而言之的话,就是 static/ 目录下的文件并不会被 Webpack 处理。
step3 修改路由文件router/index.js,将默认路由指向商品列表页。
import Vue from 'vue'
import Router from 'vue-router'
import GoodsList from '@/views/GoodsList/GoodsList'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'GoodsList',
component: GoodsList
}
]
})
step4 修改APP.vue,去掉style内容和style标签,去掉style标签是防止在头部生成多余的空标签。
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
step5 将resources/css文件夹copy到src/assets下,修改main.js,引入css文件。
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import './assets/css/base.css'
import './assets/css/login.css'
import './assets/css/product.css'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
step6:重新运行我们的项目。如下:
到这里,我们已经能够在项目中展示重构提供的页面了。注意审查logo和商品图片,会发现logo是base64引入,而商品图片是地址引入。因为static/ 目录下的文件并不会被 Webpack 处理。
2. 抽取公共组件
vue很重要的思想就是组件化,对于网站的大多数页面而言,都会有头部,底部和面包屑。那么我们不妨把这三个部分抽取成项目的公共组件。
step1:抽取公共组件。在components文件夹下删除Hello.vue,新建三个vue文件如下:
将GoodList.vue文件中的header,footer和nav-breadcrumb-wrap分别剪切粘贴到对应的组件中。这里要注意,由于文件地址改变,对一些资源的引入地址也要相应改变,比如头部引入的logo.png。
step2: 引入公共组件
抽取出公共组建以后,如果页面需要这些组件,需要引入,注册以后使用。此时的GoodsList.vue代码如下:
<template>
<div>
<PageHeader></PageHeader>
<PageBread></PageBread>
<div class="accessory-result-page accessory-page">
<div class="container">
<div class="filter-nav">
<span class="sortby">Sort by:</span>
<a href="javascript:void(0)" class="default cur">Default</a>
<a href="javascript:void(0)" class="price">Price
<svg class="icon icon-arrow-short">
<use xlink:href="#icon-arrow-short"></use>
</svg>
</a>
<a href="javascript:void(0)" class="filterby stopPop">Filter by</a>
</div>
<div class="accessory-result">
<!-- filter -->
<div class="filter stopPop" id="filter">
<dl class="filter-price">
<dt>Price:</dt>
<dd><a href="javascript:void(0)">All</a></dd>
<dd>
<a href="javascript:void(0)">0 - 100</a>
</dd>
<dd>
<a href="javascript:void(0)">100 - 500</a>
</dd>
<dd>
<a href="javascript:void(0)">500 - 1000</a>
</dd>
<dd>
<a href="javascript:void(0)">1000 - 2000</a>
</dd>
</dl>
</div>
<!-- search result accessories list -->
<div class="accessory-list-wrap">
<div class="accessory-list col-4">
<ul>
<li>
<div class="pic">
<a href="#"><img src="../../../static/1.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">999</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/2.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">1000</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/3.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">500</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
<li>
<div class="pic">
<a href="#"><img src="../../../static/4.jpg" alt=""></a>
</div>
<div class="main">
<div class="name">XX</div>
<div class="price">2499</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入购物车</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<PageFooter></PageFooter>
</div>
</template>
<script>
import PageHeader from '../../components/PageHeader'
import PageBread from '../../components/PageBread'
import PageFooter from '../../components/PageFooter'
export default {
data () {
return {}
},
components: {
PageHeader,
PageBread,
PageFooter
}
}
</script>
step3:修改面包屑组件
之前我们的面包屑的二级目录固定写死为Goods,作为公共组件肯定是不可以的。所以我们需要使用插槽slot。
PageBread.vue作如下修改:
<nav class="nav-breadcrumb">
<a href="/">Home</a>
<slot></slot>
</nav>
GoodsList.vue作如下修改:
<PageBread>
<span>Goods</span>
</PageBread>
提交代码
好的,本篇的任务完成,我们添加文件并提交到github。步骤如下:
git status
git diff
git add .
git commit -am 'add views GoodsList and Components head foot bread'
git push