Day1
Vue前台项目
技术架构:vue+webpack+vuex+vue-router-axios-less
- 封装通用组件
- 登陆注册
- token
- 守卫
- 购物车
- 支付
- 项目性能优化
Vue后台项目
技术架构:vue+webpack+vuex+vue-router-axios-scss+elmentUI
- elementUI
- 菜单权限
- 按钮权限
- 数据可视化
2、项目开始
创建一个文件夹
利用cmd加载vue create +名称
D:\项目\project-hph>vue create app
vue create is a Vue CLI 3 only command and you are using Vue CLI 2.9.6.
You may want to run the following to upgrade to Vue CLI 3:
npm uninstall -g vue-cli
npm install -g @vue/cli
出现这个先卸载,再重新安装
node_modules文件夹放置的是项目的依赖
public文件夹放置的是静态资源(图片),webpack进行打包的时候,会原封不动的打包到dist文件夹
src源代码文件夹:
assets文件夹:一般放置的也是静态资源(多个组件公用的静态资源),需要注意的是,放置在assets文件夹里面的静态资源,在webpack打包的时候,会将静态资源当作一个模块,打包到JS文件里面。
component:非路由组件,全局组件。
app.vue :根组件
main.js : 程序的入口文件
babel.config.js 配置文件,es6翻译到es5
package.json 记录项目叫什么,项目依赖,怎么运行
package-lock.json
结构层<template>
样式层<style>
行为层<script>
2.1 项目运行时,浏览器自动打开。
--package.json
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
在vue.config.json中添加下面代码,就不会出现0.0.0.8080了
devServer: { host: 'localhost', port: 8080, }
2.2 eslint校验功能关闭
vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false/*关闭校验功能*/
})
2.3 src文件夹简写方法,配置别名@
创建 js.config.json文件
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*" @代表的是src文件夹
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"exclude": [
"node_modules", //在这两个文件夹中是不能使用的
"dist"
]
}
3、项目路由的分析
前端路由:KV键值对
key:URL地址栏中的路径
value:相应的路由组件
路由组件:home首页路由组件,search路由组件,login登陆路由,Register注册路由
非路由组件:header footer【首页和搜索页】
4、完成非路由组件header与footer业务
业务逻辑
1、书写静态页面,HTML和css
2、拆分组件
3、获取服务器数据的动态数据
4、完成相应的动态的业务逻辑
注意:1、创建组件的时候,组件结构,组件的样式,图片资源
2、项目采用less样式,浏览器不识别less样式,需要通过less,less-loader进行处理less,把less变成css样式。安装依赖。
D:\项目\project-hph\app>cnpm install --save less less-loader@5
3、如果想让组件识别less样式,需要在style标签身上加上 lang=“less”
<template>
<header class="header">
<!-- 头部的第一行 -->
<div class="top">
<div class="container">
<div class="loginList">
<p>尚品汇欢迎您!</p>
<p>
<span>请</span>
<a href="#">登录</a>
<a href="#" class="register">免费注册</a>
</p>
</div>
<div class="typeList">
<a href="#">我的订单</a>
<a href="#">我的购物车</a>
<a href="#">我的尚品汇</a>
<a href="#">尚品汇会员</a>
<a href="#">企业采购</a>
<a href="#">关注尚品汇</a>
<a href="#">合作招商</a>
<a href="#">商家后台</a>
</div>
</div>
</div>
<!--头部第二行 搜索区域-->
<div class="bottom">
<h1 class="logoArea">
<a class="logo" title="尚品汇" href="#" target="_blank">
<img src="./images/logo.png" alt="">
</a>
</h1>
<div class="searchArea">
<form action="###" class="searchForm">
<input type="text" id="autocomplete" class="input-error input-xxlarge" />
<button class="sui-btn btn-xlarge btn-danger" type="button">搜索</button>
</form>
</div>
</div>
</header>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped lang="less">
.header {
&>.top {
background-color: #eaeaea;
height: 30px;
line-height: 30px;
.container {
width: 1200px;
margin: 0 auto;
overflow: hidden;
.loginList {
float: left;
p {
float: left;
margin-right: 10px;
.register {
border-left: 1px solid #b3aeae;
padding: 0 5px;
margin-left: 5px;
}
}
}
.typeList {
float: right;
a {
padding: 0 10px;
&+a {
border-left: 1px solid #b3aeae;
}
}
}
}
}
&>.bottom {
width: 1200px;
margin: 0 auto;
overflow: hidden;
.logoArea {
float: left;
.logo {
img {
width: 175px;
margin: 25px 45px;
}
}
}
.searchArea {
float: right;
margin-top: 35px;
.searchForm {
overflow: hidden;
input {
box-sizing: border-box;
width: 490px;
height: 32px;
padding: 0px 4px;
border: 2px solid #ea4a36;
float: left;
&:focus {
outline: none;
}
}
button {
height: 32px;
width: 68px;
background-color: #ea4a36;
border: none;
color: #fff;
float: left;
cursor: pointer;
&:focus {
outline: none;
}
}
}
}
}
}
</style>
4.1 使用组件的步骤(非路由组件)
-创建或者定义:components文件夹—>Header文件夹—>index.vue-上面的代码
-引入:在App.vue中引入
-注册
<script>
//引入头部组件,之后注册
import Header from './components/Header'
//在export default中注册
export default {
name: 'App',
components: {
Header
}
}
</script>
-使用
<template>
<div>
<Header></Header>
</div>
</template>
<script>
//引入头部组件,之后注册
import Header from './components/Header'
//在export default中注册
export default {
name: 'App',
components: {
Header
}
}
</script>
<style>
</style>
在静态资源public中的index.html中引入清除默认样式reser.css,reser.css放置在public中
<!--引入清除默认的样式-->
<link rel="stylesheet" href="./reset.css">
4.2 footer
1、在footer文件夹中创建index.vue
<template>
<!-- 底部 -->
<div class="footer">
<div class="footer-container">
<div class="footerList">
<div class="footerItem">
<h4>购物指南</h4>
<ul class="footerItemCon">
<li>购物流程</li>
<li>会员介绍</li>
<li>生活旅行/团购</li>
<li>常见问题</li>
<li>购物指南</li>
</ul>
</div>
<div class="footerItem">
<h4>配送方式</h4>
<ul class="footerItemCon">
<li>上门自提</li>
<li>211限时达</li>
<li>配送服务查询</li>
<li>配送费收取标准</li>
<li>海外配送</li>
</ul>
</div>
<div class="footerItem">
<h4>支付方式</h4>
<ul class="footerItemCon">
<li>货到付款</li>
<li>在线支付</li>
<li>分期付款</li>
<li>邮局汇款</li>
<li>公司转账</li>
</ul>
</div>
<div class="footerItem">
<h4>售后服务</h4>
<ul class="footerItemCon">
<li>售后政策</li>
<li>价格保护</li>
<li>退款说明</li>
<li>返修/退换货</li>
<li>取消订单</li>
</ul>
</div>
<div class="footerItem">
<h4>特色服务</h4>
<ul class="footerItemCon">
<li>夺宝岛</li>
<li>DIY装机</li>
<li>延保服务</li>
<li>尚品汇E卡</li>
<li>尚品汇通信</li>
</ul>
</div>
<div class="footerItem">
<h4>帮助中心</h4>
<img src="./images/wx_cz.jpg">
</div>
</div>
<div class="copyright">
<ul class="helpLink">
<li>关于我们
<span class="space"></span>
</li>
<li>联系我们
<span class="space"></span>
</li>
<li>关于我们
<span class="space"></span>
</li>
<li>商家入驻
<span class="space"></span>
</li>
<li>营销中心
<span class="space"></span>
</li>
<li>友情链接
<span class="space"></span>
</li>
<li>关于我们
<span class="space"></span>
</li>
<li>营销中心
<span class="space"></span>
</li>
<li>友情链接
<span class="space"></span>
</li>
<li>关于我们</li>
</ul>
<p>地址:北京市昌平区宏福科技园综合楼6层</p>
<p>京ICP备19006430号</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Footer"
}
</script>
<style scoped>
</style>
2、在根组件App.vue中引入Footer组件
<template>
<div>
<Header></Header>
<Footer></Footer>
</div>
</template>
<script>
//引入头部组件,之后注册
import Header from './components/Header'
import Footer from './components/Footer'
//在export default中注册
export default {
name: 'App',
components: {
Header,
Footer
}
}
</script>
3、引入footer的样式,在index.vue中
<template>
<!-- 底部 -->
<div class="footer">
<div class="footer-container">
<div class="footerList">
<div class="footerItem">
<h4>购物指南</h4>
<ul class="footerItemCon">
<li>购物流程</li>
<li>会员介绍</li>
<li>生活旅行/团购</li>
<li>常见问题</li>
<li>购物指南</li>
</ul>
</div>
<div class="footerItem">
<h4>配送方式</h4>
<ul class="footerItemCon">
<li>上门自提</li>
<li>211限时达</li>
<li>配送服务查询</li>
<li>配送费收取标准</li>
<li>海外配送</li>
</ul>
</div>
<div class="footerItem">
<h4>支付方式</h4>
<ul class="footerItemCon">
<li>货到付款</li>
<li>在线支付</li>
<li>分期付款</li>
<li>邮局汇款</li>
<li>公司转账</li>
</ul>
</div>
<div class="footerItem">
<h4>售后服务</h4>
<ul class="footerItemCon">
<li>售后政策</li>
<li>价格保护</li>
<li>退款说明</li>
<li>返修/退换货</li>
<li>取消订单</li>
</ul>
</div>
<div class="footerItem">
<h4>特色服务</h4>
<ul class="footerItemCon">
<li>夺宝岛</li>
<li>DIY装机</li>
<li>延保服务</li>
<li>尚品汇E卡</li>
<li>尚品汇通信</li>
</ul>
</div>
<div class="footerItem">
<h4>帮助中心</h4>
<img src="./images/wx_cz.jpg">
</div>
</div>
<div class="copyright">
<ul class="helpLink">
<li>关于我们
<span class="space"></span>
</li>
<li>联系我们
<span class="space"></span>
</li>
<li>关于我们
<span class="space"></span>
</li>
<li>商家入驻
<span class="space"></span>
</li>
<li>营销中心
<span class="space"></span>
</li>
<li>友情链接
<span class="space"></span>
</li>
<li>关于我们
<span class="space"></span>
</li>
<li>营销中心
<span class="space"></span>
</li>
<li>友情链接
<span class="space"></span>
</li>
<li>关于我们</li>
</ul>
<p>地址:北京市昌平区宏福科技园综合楼6层</p>
<p>京ICP备19006430号</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Footer"
}
</script>
<style scoped lang="less">
.footer {
background-color: #eaeaea;
.footer-container {
width: 1200px;
margin: 0 auto;
padding: 0 15px;
.footerList {
padding: 20px;
border-bottom: 1px solid #e4e1e1;
border-top: 1px solid #e4e1e1;
overflow: hidden;
padding-left: 40px;
.footerItem {
width: 16.6666667%;
float: left;
h4 {
font-size: 14px;
}
.footerItemCon {
li {
line-height: 18px;
}
}
&:last-child img {
width: 121px;
}
}
}
.copyright {
padding: 20px;
.helpLink {
text-align: center;
li {
display: inline;
.space {
border-left: 1px solid #666;
width: 1px;
height: 13px;
background: #666;
margin: 8px 10px;
}
}
}
p {
margin: 10px 0;
text-align: center;
}
}
}
}
</style>
5、路由组件的搭建 vue-router
在上面分析的时候,路由组件应该有四个:Home、Search、Login、Register
--components文件夹:经常放置的非路由组件(公用全局组件)
--pages|views文件夹:经常放置路由组件,在src中创建pages文件夹。在pages文件夹中创建Home、Search、Login、Register文件夹,在其中分别创建index.vue文件
5.1 配置路由 cnpm install --save vue-router
项目当中配置的路由一般放置在router文件夹中,在src中创建router文件夹。在router中创建index.js
import Vue from 'Vue';
import VueRouter from 'vue-router'
//使用插件
Vue.use(VueRouter);
//引入路由组件
import Home from '@/pages/Home'
import Search from '@/pages/Search'
import Login from '@/pages/Login'
import Register from '@/pages/Search'
//配置路由,对外暴露
export default new VueRouter({
//配置路由
routes:[
{
path:'/home',
component:Home
},
{
path:'/search',
component:Search
},
{
path:'/login',
component:Login
},
{
path:'/register',
component:Register
},
//重定向:在项目跑起来的时候,访问 / 的时候,立马让它定向到首页
{
path:'*',
redirect:'/home'
}
]
})
//之后回到入口文件,main.js中去注册,引入路由
在main.js中引入路由
import Vue from 'vue'
import App from './App.vue'
//引入路由
import router from '@/router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
//注册路由
router
}).$mount('#app')
vue-router版本高的解决方法
(1):卸载原有的Vue_router,并重新下载“^3.5.2”,卸载和按照的两种命令如下。
卸载原有路由:npm uninstall vue-router
安装3.0版本:npm i vue-router@3.5.2
(2):在命名后添加--legacy-peer-deps即可绕过peerDependency自动安装,保证各个引入的依赖之间对自身所使用的不同版本modules共存。
npm i vue-router@3.5.2 -legacy-peer-deps
在App.vue中写路由组件出口的地方
<template>
<div>
<Header></Header>
<!--路由组件出口的地方-->
<router-view></router-view>
<Footer></Footer>
</div>
</template>
<script>
//引入头部组件,之后注册
import Header from './components/Header'
import Footer from './components/Footer';
//在export default中注册
export default {
name: 'App',
components: {
Header,
Footer
}
}
</script>
<style>
</style>
5.2 总结
路由组件和非路由组件的区别?
- 路由组件一般放置在pages|views文件夹中,非路由组件放置在components文件夹中
- 路由组件一般需要在router文件夹中的index.js进行注册(使用的即为组件的名字),非路由组件在使用的时候,一般都是以标签的形式使用
- 注册完路由,不管路由组件还是非路由组件身上都有$route、$router属性
- 在index.js中重定向
-
//重定向:在项目跑起来的时候,访问 / 的时候,立马让它定向到首页 { path:'*', redirect:'/home' } -
$route:一般获取路由信息【路径、query、params】 $router:一般进行编程式导航,进行路由跳转【push|replace】
5.3 路由的跳转
路由的跳转有两种形式:
- 声明式导航router-link,可以进行路由的跳转
- 编程式导航push|replace,进行路由的跳转(编程式导航可以做声明式导航的功能,还可以做一些其他的业务逻辑)
在component中的Header的index.vue
<div class="loginList">
<p>尚品汇欢迎您!</p>
<p>
<span>请</span>
<!--声明式导航:务必要有to属性-->
<router-link to="/login">登录</router-link>|
<router-link class="register" to="/register">免费注册</router-link>
</p>
</div>
<div class="searchArea">
<form action="#" class="searchForm">
<input type="text" id="autocomplete" class="input-error input-xxlarge" />
<button class="sui-btn btn-xlarge btn-danger" type="button" @click="goSearch">搜索</button>
</form>
</div>
<script>
export default {
name: "Header",
methods:{
//搜索按钮的回调函数:需要向search进行跳转
goSearch(){
this.$router.push('/search')
}
}
}
</script>
6、footer组件的显示与隐藏
显示和隐藏组件:v-if v-show
footer:在home、search显示footer组件
footer组件:在登录和注册时隐藏
<!--在Home、Search 显示,在登录、注册隐藏。-->
<Footer v-show="$route.path=='/home'||$route.path=='/search'"></Footer>
面试题:v-show与v-if区别?
v-show:通过样式display控制
v-if:通过元素上树与下树进行操作
面试题:开发项目的时候,优化手段有哪些?
1:v-show|v-if
2:按需加载
6.1 我们可以根据组件身上的$route获取当前的路由信息,通过路由路径判断Footer显示与隐藏
在router中的index.js 的配置路由中 添加路由元信息
meta:{show:true }
//配置路由的地方
//引入vue和vueRouter
import Vue from 'vue';
import VueRouter from 'vue-router';
//使用插件
Vue.use(VueRouter);
//引入路由组件
import Home from '@/pages/Home/index'
import Search from '@/pages/Search'
import Login from '@/pages/Login'
import Register from '@/pages/Register'
//配置路由,对外暴露
export default new VueRouter({
//配置路由
//在配置路由中添加meta:{show:true|false}
routes:[
{
path:'/home',
component:Home,
meta:{
show:true
}
},
{
path:'/search',
component:Search,
meta:{
show:true
}
},
{
path:'/login',
component:Login,
meta:{
show:false
}
},
{
path:'/register',
component:Register,
meta:{
show:false
}
},
//重定向:在项目跑起来的时候,访问 / 的时候,立马让它定向到首页
{
path:'*',
redirect:'/home'
}
]
})
//之后回到入口文件,main.js中去注册,引入路由
在App.vue中配置footer
<Footer v-show="$route.meta.show"></Footer>
meta:路由元信息
根据当前路由的信息:route.meta.show
进行判断:show的值为true还是false
6.2 配置路由的时候可以添加路由元信息meta
7、路由传参
7.1 路由跳转的方式
- 声明式导航:router-link(务必要有to属性),可以实现路由的跳转
-
<router-link to="#"></router-link> - 编程式导航:利用的是组件实例的 $route.push|replace 方法
- 编程式导航更好用:因为可以书写自己的业务逻辑
7.2 路由传参,参数有几种写法
params参数:属于路径当中的一部分,在配置的路由的时候需要占位
query参数:不属于路径当中的一部分,类似于AJAX中的queryString /home?k=v&kv= 不需要占位
7.2.1 路由传递参数-字符串形式
1、在Header.vue中,先获取表单数据,也就是搜索框里面输入的值。
<script>
export default {
name: "Header",
//获取表单数据
data(){
return{
keyword:''
}
},
methods:{
//搜索按钮的回调函数:需要向search进行跳转
goSearch(){
this.$router.push('/search')
}
}
}
</script>
2、收集文本框里面的值
<!--收集文本框的数据,v-model="keyword" 双向数据绑定-->
<input type="text" id="autocomplete" class="input-error input-xxlarge" v-model="keyword"/>
3、在index.js 中配置路由
routes[
{
path:'/search/:keyword', 占位
component:Search,
meta:{
show:true
}
}
]
4、传递搜索框里面的函数到search中
<script>
export default {
name: "Header",
//获取表单数据
data(){
return{
keyword:''
}
},
methods:{
//搜索按钮的回调函数:需要向search进行跳转
goSearch(){
//路由传递参数:
//第一种:字符串形式
this.$router.push('/search/'+this.keyword+"?k="+this.keyword.toUpperCase());
//
}
}
}
</script>
$route
path:"/search/abc"
query:Object
k:"ABC"
params:Object
keyword:"abc"
fullPath:"/search/abc?k=ABC"
在search中展示出来
7.2.2 模板字符串
//第二种:模板字符串
//this.$router.push('/search/${this.keyword}?k=${this.keyword.toUpperCase}')
7.2.3 **(常用的形式)对象的写法
先在配置路由中给Search路由取个名字
{
path:'/search/:keyword',
component:Search,
meta:{
show:true
},
name:"search"
},
methods:{
//搜索按钮的回调函数:需要向search进行跳转
goSearch(){
//路由传递参数:
//第一种:字符串形式
//this.$router.push('/search/'+this.keyword+"?k="+this.keyword.toUpperCase());
//第二种:模板字符串
//this.$router.push('/search/${this.keyword}?k=${this.keyword.toUpperCase}')
//第三种:对象
this.$router.push({name:"search",params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}})
}
}
8、路由相关的面试题
1:路由传递参数(对象写法)path是否可以结合params参数一起使用?
this.$router.push({path:"/search",params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}})
答:路由传参的时候,对象的写法可以是name、path形式,但是需要注意的是,path和params不能一起用。
2:如何指定params参数可传可不传?
答:配置路由的时候,占位了(params参数),但是路由跳转的时候就不传递。
路径会出现问题:localhost:8080/#/?k=QWE
localhost:8080/#/search?k=QWE
如何指定params参数可传可不传,在配置路由的时候,在占位的后面加上一个问号?
this.$router.push({name:"search",query:{k:this.keyword.toUpperCase()}})
path:'/search/:keyword?'
3:params参数可以传递也可以不传递,但是如果传递是空串,如何解决?
this.$router.push({name:"search",params:{keyword:''},query:{k:this.keyword.toUpperCase()}})
使用undefined解决:params参数可以传递,可以不传递(空的字符串)
this.$router.push({name:"search",params:{keyword:''||undefined},query:{k:this.keyword.toUpperCase()}})
4: 路由组件能不能传递props数据? 可以的:三种写法
1、布尔值写法:在路由配置中
{
path:'/search/:keyword',
component:Search,
meta:{
show:true
},
name:"search",
//路由组件能不能传递props数据
//布尔值写法
props:true
},
在搜索的index.vue中
<script>
export default {
name: "Search"
props:['keyword']
}
</script>
//对象写法:额外的给路由组件传递一些props
//props:{a:1,b:2}
//函数写法:可以把params参数、query参数,通过props传递给路由组件
props:($route)=>{
return{keyword:$route.params.keyword(),k:$route.query.k};
}

浙公网安备 33010602011771号