目录
前端vue项目创建及配置
在当前文件夹下输入cmd启动命令窗口
vue create xxx//项目名称
可先修改淘宝镜像加速
问题:防止在项目的编写过程中频繁报错//如果有eslint插件可以先停用
解决方法:
vue.config.js里面添加或配置如下:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false
})
问题:vue文件第一行有波浪线提示,虽然项目能正常运行。
解决方法:在package.json文件下找到"parserOptions",添加或配置如下:
"parserOptions": {
"parser": "@babel/eslint-parser",
"requireConfigFile" : false
},
项目路由的搭建
路由跳转的地方需要router-link来指定
在文件夹下创建router文件夹用来存放
// 引入库
import Vue from 'vue'
import VueRouter from 'vue-router'
// 需要的组件
import Home from '@/pages/Home'
import Login from '@/pages/Login'
import Search from '@/pages/Search'
import Register from '@/pages/Register'
Vue.use(VueRouter);
export default new VueRouter({
// 配置路由
routes: [{
path: '/home',
component: Home,
meta: {
show: true
}
},
{
path: '/login',
component: Login,
meta: {
show: true
}
},
{
path: '/register',
component: Register,
meta: {
show: false
}
},
{
path: '/search',
component: Search,
meta: {
show: false
},
},
// 对一开始访问进行重定向
{
path:'*',
redirect:'/home'
}
]
})
在全局Vue的main.js里面注册router方便进行全局调用
import router from '@/router'
new Vue({
render: h => h(App),
// 注册路由
router,
store
}).$mount('#app')
在app组件里面放置要插入的位置
<router-view></router-view>
多次点击push和replace报错问题
原因:push是一个promise,promise需要传递成功和失败两个参数,我们的push中没有传递。
方法:this.$router.push({name:‘Search’,params:{keyword:“…”||undefined}},()=>{},()=>{})后面两项分别代表执行成功和失败的回调函数。
这种写法治标不治本,将来在别的组件中push|replace,编程式导航还是会有类似错误
push是VueRouter.prototype的一个方法,在router中的index重写该方法即可
//不懂可参考js原型链
重写push和replace方法
let originpush=VueRouter.prototype.push;
let originreplace=VueRouter.prototype.replace;
VueRouter.prototype.push=function(location,resolve,reject){
if(resolve&&reject){
originpush.call(this,location,resolve,reject);
}else{
originpush.call(this,location,()=>{},()=>{});
}
}
VueRouter.prototype.replace=function(location,resolve,reject){
if(resolve&&reject){
originreplace.call(this,location,resolve,reject);
}else{
originreplace.call(this,location,()=>{},()=>{});
}
}
axios二次封装及api统一管理
axios二次封装
// 对axios进行二次封装
import axios from "axios";
const requsets=axios.create({
// 基础路径自动添加
baseURL:"/api",
// 请求5秒超时自动取消
timeout:5000
})
// 请求拦截器
requsets.interceptors.request.use((config)=>{
// headers请求头
return config;
})
requsets.interceptors.response.use((res)=>{
// 成功的回调函数,服务器返回数据回来后,相应拦截器检测到,可修改
return res.data;
},(err)=>{
return Promise.reject(new Error('faile'))
})
export default requsets;
api统一管理
项目小可选择在每个组件中单独写
大型项目可在同级中创建index.js进行统一管理
import requests from "./requests";
export const reqCategoryList = () => requests({
url: '/product/getBaseCategoryList',//路径
method: 'get'//请求方式
});
// 引用方式import {reqCategoryList} from '@/api'
跨域解决
在Vue.config.js里添加
devServer: {
proxy: {
'/api': {//匹配以api开头的路径
target: 'http://gmall-h5-api.atguigu.cn', //目标基础路径
},
},
},
nprogress进度条
网址栏下的进度条(颜色在css里的.bar里修改)
// 引用进度条
import nProgress from "nprogress";
// 进度条样式
import 'nprogress/nprogress.css'
// 请求拦截器
requests.interceptors.request.use((config)=>{// headers请求头
// 进度条开始动
nProgress.start();
return config;
})
// 成功的回调函数,服务器返回数据回来后,相应拦截器检测到,可修改
requests.interceptors.response.use((res)=>{
// 进度条停止动
nProgress.done();
return res.data;
},(err)=>{
return Promise.reject(new Error('faile'))
})
vuex
集中式管理数据(相当与一个全局变量库)
版本要求:
在vue2中,要用vuex的3版本
npm#
npm install vuex@3 --save
Yarn#
yarn add vuex@3 --save
在vue3中,要用vuex的4版本
新建文件夹store=>index.js:
import Vue from "vue";
import Vuex from 'vuex';
//需要使用插件一次
Vue.use(Vuex);
import home from './home';
import search from './search'
export default new Vuex.Store({
modules:{
home,
search
}
})
home=>index.js
// state:仓库存储数据的地方
const state={};
// mutations:修改state的唯一地方
const mutations={};
// action:处理action,可以写业务逻辑
const actions={};
// getters:理解为计算属性
const getters={};
export default {
state,
mutations,
actions,
getters
}
三级联动动态实现
在TypeNav组件里面通知vuex让其发送请求给服务器
// 挂载完成之后
mounted() {
this.$store.dispatch("categoryList")
},
在对应的仓库中去配置actions,mutations,states
import { reqCategoryList } from "@/api";
// state:仓库存储数据的地方
const state={
categoryList:[],
};
// mutations:修改state的唯一地方
const mutations={
// 存储到变量中
CATEGORYLIST(state,categoryList){
state.categoryList=categoryList
}
};
// action:处理action,可以写业务逻辑
const actions={
// promise语法
async categoryList(state){
let result=await reqCategoryList();
if(result.code===200){
// 发送获取的数据给mutations进行处理
state.commit("CATEGORYLIST",result.data)
}
}
};
回到TypeNav组件里面去调用mapState(需调用)映射数据
调用方法:import {mapState} from 'vuex'
computed: {
...mapState({
categoryList:state=>state.home.categoryList
})
},
到页面进行渲染
<div class="item" v-for="(c1, index) in categoryList" :key="c1.categoryID">
<h3>
<a href="">{{ c1.categoryName }}</a>
</h3>
<div class="item-list clearfix">
<div class="subitem">
<dl
class="fore"
v-for="(c2, index) in c1.categoryChild"
:key="c2.categoryID"
>
<dt>
<a href="">{{ c2.categoryName }}</a>
</dt>
<dd>
<em v-for="(c3, index) in c2.categoryChild" :key="c3.categoryID">
<a href="">{{ c3.categoryName }}</a>
</em>
</dd>
</dl>
</div>
</div>
mock模拟数据
创建后如下
api/mockAjax.js:专门请求mock接口的axios封装(可参考axios的二次封装)
src/mock/banners.json(模拟的数据)
src/mock/mockServer.js 代码如下
api/index.js注册函数
入口文件注册
/*
利用mockjs来mock数据接口
*/
import Mock from 'mockjs'
import banners from './banners.json'
import floors from './floors.json'
// 提供广告位轮播数据的接口
Mock.mock('/mock/banners',{
code: 200,
data: banners
})
// 提供所有楼层数据的接口
Mock.mock('/mock/floors',{
code: 200,
data: floors
})
全局事件总线
子this.$bus.$emit("name",value)
父this.$bus.$on("name",value=>{})
自定义绑定
父里的子组件<SearchSelector @markInfo="markInfo" />
子methods里
markHandler(item){
this.$emit("markInfo",item)
},
滚轮事件
每次
scrollBehavior(to, from, savedPosition) {
// 始终滚动到顶部
return { y: 0 }
},
v-if/v-show渲染服务器返回数据能运行但报错
在store仓库中运用getters来解决
spuSaleAttrList(state){
return state.goodsInfo.spuSaleAttrList||[];
}
返回一个空让其不会报错
原因:在解析模板时仓库还未拿到数据并返回存在异步操作的问题,只能先返回空数组
Token
服务器下发的用户的唯一标识字符串
全局路由守卫
const router= new VueRouter({
// 配置路由
routes,
});
router.beforeEach((to,from,next)=>{
})
export default router;
开发心得
先完成组件的静态->在router里面注册组件->在api中封装后台接口->vuex中使用3连环(action,mutations,state)->在组件中调用接口用mapState把数据加载到组件中->如果组件存在操作后台数据的话封装getData函数来调用接口方便在mouted和操作完数据后重新获取最新数据