目录
一、清空项目非必要文件
二、样式初始化
三、网站结构布置
四、网站数据请求模块
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.js
中about
的路由注释掉。- 删除
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>
效果展示:
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中,重复点击同一个路由会出现以下报错:
方案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);
})
};