目录

一、清空项目非必要文件

二、样式初始化

三、网站结构布置

四、网站数据请求模块

4.1、发起请求

4.2、代理配置

4.3、API与Request封装

4.4、发起请求

五、头部组件

5.1、版心样式

5.2、基本布局

5.3、Vue中关于Can't resolve 'less-loader' in...错误

 六、路由配置

关于重复点击同一个路由出现的报错问题解决



项目搭建前的命令行

确保node和npm 已经全局安装好了(node -v和npm -v检查版本)

1、下载vue库文件:npm init -y   (初始化)                npm  i  -S  vue@2 

       引用: <script src="./node_modules/vue/dist/vue.js"></script>

2、vue/cli 脚手架--5x:

安装cnpm:npm install cnpm --registry=https://registry.npm.taobao.org  -g

cnpm install -g @vue/cli
vue --version
vue create 项目名(不要中文空格特殊符号)
npm run serve/npm start
 vetur插件

3、自动开启浏览器与端口修改:找到vue.config.js文件

// 设置浏览器自动开启
  devServer:{
    open:true,//设置自动开启
    port:8888,//修改端口
    host:"localhost"
...
}

4、json-server模拟数据

(1)安装 npm i json-server -g

(2)在项目中新建一个mock文件夹,并且创建db.json文件用来容纳模拟数据文件

(3)cd到mock文件夹下:json-server --watch db.json --port 端口号

5、打包生产环境

npm run build

配置生产环境

(1)在vue.config.js中设置 publicPath:"./"  
(2)把路由模式设置为hash

重新build

6、sass的安装:npm install -g sass

sass --version

一、清空项目非必要文件

集成终端 vue create 项目名【安装过pnpm命令为vue create 项目名 -m npm】 创建项目之后

  • views 下面的文件只保留 Home.vue ,其余删除,删除 components/HelloWorld.vue,并且 Home.vue 中不再引入 HelloWorld 组件。
  • 删除 src/assets 下的图片,换成我们的img文件夹。
  • 建议在src包下的assets文件夹里面放img/css文件夹等公共资源。
  • router/index.jsabout 的路由注释掉。
  • 删除 App.vue 中的less样式。

二、样式初始化

开始书写结构样式时,发现页面会有自带的间距,这是浏览器本身的默认样式,所以我们需要进行样式初始化,清除浏览器默认样式。

安装初始化样式库reset-css:

npm i reset-css 或者   yarn add reset-css

安装成功后在main.js中引入即可:

import "reset-css"

可以查看设计稿的详细px,以及样式,可以直接复制样式在代码直接使用。

三、网站结构布置

在App.vue中设置好头部,导航和尾部组件:

<template>
  <div id="app">
        <Tabbar></Tabbar>
        <Header></Header>
        <router-view/>
        <Footer></Footer>
  </div>
</template>
<script>
import Header from '@/components/Header'
import Tabbar from '@/components/Tabbar'
import Footer from '@/components/Footer'

export default {
    components:{
        Header,Tabbar,Footer
    },
   
}
</script>

在@/components目录下新建Header,Tabbar,Footer三个组件即可

四、网站数据请求模块

4.1、发起请求

作为一个网站前端,数据请求模块少不了。我们需要安装axios模块:

npm i axios  /   cnpm install --save axios

(1)最原始的请求写法

import axios from "axios"
export default {
  	...
   created(){
   axios.get("http://kumanxuan1.f3322.net:8881/cms/products/recommend ")
    .then(res=>{
      	console.log(res.data);
    })
    .catch(err=>{
      	console.log(err);
    })
},
}

4.2、代理配置

我们对 vue.config.js 进行配置:

devServer: {
    port: 8080,
    proxy: {
        '/api': {
            target: "http://kumanxuan1.f3322.net:8881/cms",
            pathRewrite: {
                '^/api': ''
            }
        }
    }
}

由于配置文件修改了,这里一定要记得重新 yarn serve / npm run serve!!

4.3、API与Request封装

src 下新建 request目录 ,在request目录下新建 request.js

request.js 中:

import axios from "axios"

const instance = axios.create({
    baseURL:"http://kumanxuan1.f3322.net:8881/cms",
    timeout:5000
})
// 设置请求拦截器
instance.interceptors.request.use(config=>{
    // console.log("每一次发起请求前,都会先执行这里的代码");
    // console.log(config); //config是一个对象:记录了本次请求的配置信息
    return config
},err=>{
    return Promise.reject(err)
})
// 设置响应拦截器:对服务器响应回来的数据做统一处理
instance.interceptors.response.use(res=>{
    // console.log("每一次接收到响应,都会先执行这里的代码,再去执行成功的那个回调函数then");
    // res :是一个对象:原先说的axios封装的res对象
    return res
},err=>{
    return Promise.reject(err)
})

export default instance

为了更好地管理我们的这些接口,我们把所有请求都抽取出来在一个api.js中

request目录下新建api.js,api.js 中:

import request from './request'

// 请求精品推荐数据
export const JingpinAPI = () => request.get('/products/recommend')

本项目中所有接口在api.js中:

分为Get请求方式系列+携带参数Post请求方式系列+携带参数两大类。

import request from './request'
import qs from "qs"
// ===============================Get请求方式系列+携带参数
// 获取登录用户信息
export const UserProfilesAPI = () => request.get('/shop/userProfiles')
// 请求"精品推荐"数据
export const JingpinAPI = () => request.get('/products/recommend')
// 请求"热门兑换"数据
export const ReMenAPI = () => request.get('/products/hot')
// 请求购物车数据
export const CartDataApi = () => request.get(`/shop/carts`);
// 请求"商品详情"数据【id跳转页面】
export const GoodDetailsAPI = (id) => request.get(`/products/${id}`)
// 商品搜索(含首页的“更多”)【带参数】
export const GoodsSearchApi = (params) => request.get(`/products`, {params});
// ===============================Post请求方式系列+携带参数
// 发送短信验证码请求
export const SendSMSAPI = (params) => request.post('/sendSMS',qs.stringify(params))
// console.log(qs.stringify({name:'Vue'}));        //"name=Vue"
// 手机号验证码登录(含注册)
export const PhoneLoginAPI = (params) => request.post('/phoneRegin',qs.stringify(params))
// 微信登录(这个接口必须用qs对数据进行格式化)
export const WeixinLoginApi = (params) => request.post(`/wechatUsers/PCLogin`, qs.stringify(params));
// 手机号绑定微信的登陆
export const BindPhoneApi = (params) => request.post(`/wechatUsers/binding`, qs.stringify(params));
// 加入到购物车
export const AddToCartApi = (params) => request.post(`/shop/carts/add`, qs.stringify(params));

4.4、发起请求

App.vue 中:

import {JingpinAPI} from "@/request/api"

// 方法一:容易出现“回调地狱”
//     created(){
//     JingpinAPI()
//         .then(res=>{
//             if(res.errno == 0){
//                 console.log(res.data)	// 成功拿到所有首页数据
//             }
//         })
// },
// 方法二:await new Promise(),它后面一般放Promise对象
async created(){
    let res=await JingpinAPI();
    console.log(res.data);
},

五、头部组件

5.1、版心样式

在assets在新建css目录,新建public.less文件

.wrap{
    width: 1200px;
    margin: 0 auto;
}

在main.js中全局引入

import "@/assets/css/public.less"

5.2、基本布局

处理导航项当前样式 : :class="$route.path==='/home'?'active':''"

并且设置点击跳转路由:  @click="$router.push('/home')"

<template>
  <div class="nav">
    <div class="wrap nav-wrap">
      <div class="l">
        <h1>
          <img src="../assets/img/indexLogo.6f8ac4f0.png" alt="" />
        </h1>
      </div>
      <div class="c">
      <ul>                                                 
     <li @click="$router.push('/home')" :class="$route.path==='/home'?'active':''">首页</li>
     <li @click="$router.push('/goods')" :class="$route.path==='/goods'?'active':''">全部商品</li>
     <li @click="$router.push('/user')" :class="$route.path==='/user'?'active':''">个人中心</li>
     <li @click="$router.push('/order')" :class="$route.path==='/order'?'active':''">我的订单</li>
     <li @click="$router.push('/free')" :class="$route.path==='/free'?'active':''">专属福利</li>
</ul>
      </div>
      <div class="r">
        <input type="text" placeholder="输入关键字"/>
        <span class="search-btn"><img src="../assets/img/search.png" alt="" /></span>
      </div>
    </div>
  </div>
</template>

样式如下:

<style lang = "less" scoped>
.nav-wrap {
  height: 118px;
  background-color: #fcf;
  display: flex;
  justify-content: space-between;
  align-items: center;
 .c ul{
            width: 500px;
            display: flex;
            justify-content: space-between;
            color:#242B39;
            font-size: 16px;
            font-family: SourceHanSansSC-Medium;
            font-weight: 500;
            .active{
                color:#0A328E;
                font-weight: 700;
                cursor: pointer;
            }
        }
  .r{
    display: flex;
    input{
        width: 214px;
        height: 40px;
        border: 1px solid #dedede;
        border-radius: 20px 0 0 20px;
        float: left;
        box-sizing: border-box;
        padding-left: 19px;
        outline-style: none;
    }
    .search-btn{
        width: 50px;
        height: 40px;
        background: #0A328E;
        border-radius: 0px 20px 20px 0px;
        text-align: center;
        line-height: 44px;
    }
}
}
</style>

效果展示:

vue app商城首页 demo 下载 vue商城模板 pc_vue app商城首页 demo 下载

5.3、Vue中关于Can't resolve 'less-loader' in...错误

原因分析,文件中的style用了less,而项目中未安装less:

解决方法:
打开项目文件夹,终端命令:

npm install --save-dev less-loader less

 六、路由配置

在router/index.js中配置重定向,及几个导航路由:

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/goods',
    name: 'Goods',
    component: () => import(/* webpackChunkName: "goods" */ '../views/Goods.vue')
  },
  {
    path: '/user',
    name: 'User',
    component: () => import(/* webpackChunkName: "user" */ '../views/User.vue')
  },
  {
    path: '/order',
    name: 'Order',
    component: () => import(/* webpackChunkName: "dingdan" */ '../views/order.vue')
  },
  {
    path: '/free',
    name: 'Free',
    component: () => import(/* webpackChunkName: "free" */ '../views/Free.vue')
  }
]

关于重复点击同一个路由出现的报错问题解决

在新版本的vue-router中,重复点击同一个路由会出现以下报错:

vue app商城首页 demo 下载 vue商城模板 pc_vue app商城首页 demo 下载_02

方案1、vue-router降级处理(但不推荐)  

npm i vue-router@3.0.7

方案2、直接修改原型方法push(推荐)

// 把这段代码直接粘贴到router/index.js中的Vue.use(VueRouter)之前
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function(location) {
  return originalPush.call(this, location).catch(err => {
    console.log(err);
  })
};