我的前端项目放在了码云上—>vue前端
一、安装vue-router
npm install vue-router
src下创建一个文件夹
在里面创建两个文件
index.js用于配置router的相关配置,创建router对象之类的
import Vue from 'vue'
//导入路由
import VueRouter from 'vue-router'
import routers from './routers'
import {getToken} from '../libs/util'
import iView from 'view-design'
const {homeName} = require('../config')
//安装路由
Vue.use(VueRouter)
//要把这个路由配置给别的地方用,就要导出
//相当于 new 一个Router对象 然后export default 来导出,再在对象内部进行配置new Router({})
const router = new VueRouter({
// 把路由的配置选项单独写到一个文件中了
routes: routers
})
const LOGIN_PAGE_NAME = 'login'
const permitList = [ LOGIN_PAGE_NAME]
//使用 router.beforeEach 注册一个全局前置守卫
router.beforeEach((to,from ,next) => {
iView.LoadingBar.start()
const token = getToken()
console.log("****",!token)
if (token) {
next()
} else {
if (to.name === LOGIN_PAGE_NAME) {
next()
} else {
// {name: LOGIN_PAGE_NAME}
next()
}
}
// if (token) {
// next()
// }
// else if (token&& permitList.includes(to.name)) {
// // 已登录且要跳转的页面是登录页
//
// next( {
// name: homeName // 跳转到homeName页
// })
// }
// if (!token) {
// // 未登录,并且不是白名单
// next({
// name: LOGIN_PAGE_NAME// 跳转到登录页
// })
// }
// if (!token && permitList.includes(to.name)) {
// next()//跳转
// }
})
router.afterEach(to => {
// debugger
iView.LoadingBar.finish()
//scrollTo() 方法可把内容滚动到指定的坐标。
window.scrollTo(0,0)
})
export default route
router.js用于配置项目中的路由
//导入组件
import login from '../components/view/login/login'
import homepage from '../components/view/home/homepage'
import tab from '../components/view/tab/tab'
import mykitchens from '../components/view/mykitchens/mykitchens'
import err from '../components/error/401error'
import videocontent from '../components/view/videocontent/videocontent'
import register from '../components/view/register/register'
import firstPage from '../components/view/ firstpage/firstPage'
import comment from '../components/view/comment/comment'
import searchView from '../components/view/searchView/searchView'
import personalCenter from '../components/view/personalCenter/personalCenter'
import myInfo from '../components/view/personalCenter/myInfo/myInfo'
import myAvatar from '../components/view/personalCenter/myAvatar/myAvatar'
import userInfo from '../components/view/personalCenter/myInfo/userInfo'
import individualKitchen from '../components/view/individualKitchen/individualKitchen'
//具体的路由配置
export default [
//设置默认路由
{
path: '/',
name: 'firstPage',
redirect: '/firstPage',
component: firstPage
},
{
//配置路由路径(与实际路径无关)
path: '/login',
name: 'login',
//要跳去的组件
component: login
},
{
path: '/homepage',
name: 'homepage',
component: homepage,
redirect: {name: "mykitchens"},
children:[
// {
// path: '/tab',
// name: 'tab',
// component: tab
// },
{
path: '/mykitchens',
name: 'mykitchens',
component: mykitchens
},
{
path: '/individualKitchen',
name: 'individualKitchen',
component: individualKitchen
}
]
},
{
path: '/401error',
name: '401',
component: err
},
{
path: '/videocontent',
name: 'videocontent',
component: videocontent
},
{
path: '/register',
name: 'register',
component: register
},
{
path: '/firstPage',
name: 'firstPage',
component: firstPage,
// redirect: {name: 'mykitchens'},
// children: [
// {path: '/mykitchens',
// name: 'mykitchens',
// component: mykitchens}
// ]
},
{
path: '/comment',
name: 'comment',
component: comment
},
{
path: '/searchView',
name: 'searchView',
component: searchView
},
{
path: '/personalCenter',
name: 'personalCenter',
component: personalCenter,
redirect: {name: "userInfo"},
children:
[
{
path: "/userInfo",
name: "userInfo",
component: userInfo
},
{
path: "/myAvatar",
name: 'myAvatar',
component: myAvatar
},
{
path: "/myInfo",
name: 'myInfo',
component: myInfo
}
]
},
]
main.js
// 要是router中的文件名为index,那么路径只写到文件夹就可以,它会自动扫描小面的index.js文件
import router from './router'
// 全局唯一的vue对象
// eslint-disable-next-line no-new
new Vue({
el: '#app',
// 给这个vue对象配置路由
router,
render: h => h(App)
})
App.vue
<template>
<div id="app">
<router-view v-if="isRouterAlive"/>
</div>
</template>
<script>
export default {
name: 'App',
provide () { //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。
return {
reload: this.reload
}
},
data() {
return{
isRouterAlive: true //控制视图是否显示的变量
}
},
methods: {
reload () {
this.isRouterAlive = false; //先关闭,
this.$nextTick(function () {
this.isRouterAlive = true; //再打开
})
}
}
}
</script>
1. vue 路由传参的两种方式
vue 路由传参虽然有好几种写法,但本质上分为两种,一种是 get 类型的传参,一种是 post 类型的传参。
1.1. get 的传参(字符串类型)
【传参】get 类型传参的三种写法:
1.this.$router.push('/addres?id=12345')
2.this.$router.push({
path: "/addres",
query: {
id: 12345
}
})
3.this.$router.push({
name: "addres",
query: {
id: 12345
}
})
【接参】
这三种写法都是 get 类型传参,参数会跟到路由后面,且页面刷新参数不会丢失。在 addres 页面用 this.$route.query.id 就可以获取到 id 的值。
1.2. post 类型的传参
• post 传参的写法
• 【传参】
this.$router.push({
name: "addres",
params: {
id: 12345
}
})
• 【接参】
• 在 addres 页面通过 this.$route.params.id 获取 id 值。
通过这种方式传参,参数不会跟在路由后面,而且刷新页面参数会丢失。
• 注意:
1.post 类型的传参必须用 name ,如果用 path,那么 addres 页面的 params 是空的。
2.不管是 get 类型的传参还是 post 类型的传参,但凡用 name 必须要在路由里配置好 name 属性。
3.参数为 Object 类型时要注意:如下:
2、 传object类型的参数
get 的传参类型
用 query 传 Object 类型的参数
// 当前页面
let data = {
id: 1234,
name: 'test'
}
this.$router.push({
path: "/addres",
query: {
data: data
}
})
/addres 页面用 this.$route.query.data 接收参数
刷新页面之后,参数变为 “[object Object]”
为了避免这个问题,可以在传参时用 JSON.stringify(data) 把参数转为 json 格式,在 addres 页面接收到参数后再用 JSON.parse(data) 转回 Object
• post 类型的传参
用 params 传 Object 类型的参数
// 当前页面
let data = {
id: 1234,
name: 'test'
}
this.$router.push({
name: "addres",
params: {
data
}
})
addres 页面用 this.$route.params.data 接收.
post 类型的传参,刷新页面参数消失
二、使用iview
npm install view-design –save
三、.vue----js-cookie的使用方法
npm install js-cookie --save
导入引用
import Cookies from 'js-cookie'
背景:最近的vue项目中由于项目的token是需要设置过期时间的,当然,以前这种过期的行为逻辑一直是后端来控制,但这次要求前端也进行token时间的一个监控,由于懒得封装cookie,所以就用了js-cookie的一个cookie封装库
1、什么是js-cookie
看名字我们就知道这是关于cookie存储的一个js的API,根据官网描述其优点有:适用所有浏览器、接受任何字符、经过任何测试没什么bug、支持CMD和CommonJS、压缩之后非常小,仅900个字节
四、安装video-player插件
Npm安装
npm install vue-video-player --save
注意:.
vue-video-player 是根据 videojs 进行了封装 所以必须导入video.js (video.js 已经被vue-video-player安装不需要重新安装 直接导入即可)
.vue-video-player 安装完 可以在node_modules中查看 部分视频播放插件
1.在mian.js引用
import VideoPlayer from 'vue-video-player'
import 'vue-video-player/src/custom-theme.css'
Video.js被封装在了vidoe-player中,所以不用重新单独安装
import 'video.js/dist/video-js.css'
2.显示声明
Vue.use(VideoPlayer)
3.在组件中使用
注、 video-player标签的class必须设置成“video-player vjs-custom-skin”,你引入的样式才能起作用
<video-player
class="video-player vjs-custom-skin"
ref="videoPlayer"
:options="playerOptions"
:playsinline="true"
>
</video-player>
data () {
return {
videoList: [],
playerOptions: {
playbackRates: [0.5, 1.0, 1.5, 2.0], // 可选的播放速度
autoplay: false, // 如果为true,浏览器准备好时开始回放。
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 是否视频一结束就重新开始。
preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: 'zh-CN',
aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [
// {
// type: "video/mp4", // 类型
// src: '/Path/fof-video/4a226dcf-e434-4322-9cbf-58d15f5a2cc5.mp4' // url地址
// src: "https://cdn.theguardian.tv/webM/2015/07/20/150716YesMen_synd_768k_vp8.webm"
// src: 'file:///D:/fof/fof-video/123f4a64-fc97-426d-b043-791cbdc3a639.mp4'
// src: require('D:/fof/fof-video/123f4a64-fc97-426d-b043-791cbdc3a639.mp4')
// }
],
poster: '', // 封面地址
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true, // 当前时间和持续时间的分隔符
durationDisplay: true, // 显示持续时间
remainingTimeDisplay: false, // 是否显示剩余时间功能
fullscreenToggle: true // 是否显示全屏按钮
}
},
}
},
computed: {
player() {
return this.$refs.videoPlayer.player
}
},
methods:{
getVideo(){
getVideoList().then(res =>{
//接收视频对象数组
this.videoList = res.data
this.videoList.map((item,index) => {
console.log("item=>",item)
console.log("index=>",index)
const fileName = item.storagePath.substring(item.storagePath.lastIndexOf("\\")+1)
this.playerOptions.sources.push(Object.assign({},item,{src: require('D:/fof/fof-video/' + fileName),type: 'video/mp4'}))
// debugger
// this.playerOptions.sources[index].type = 'video/mp4'
// this.videoSource['src']= require(item['storagePath'])
// this.playerOptions.sources[index].src = require('D:/fof/fof-video/' + fileName)
})
console.log("videoRes=>",res)
})
},
}
遇到的问题:
1.//vue使用vue-video-player无法播放本地视频的问
解决:因为引入的是本地资源,要把资源写在“require”方法里
或者在springboot配置类添加一些虚拟路径的映射
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//@Configuration
//public class ResourceConfig implements WebMvcConfigurer {
//
// public void addResourceHandles(ResourceHandlerRegistry registry) {
//
// registry.addResourceHandler("/Path/**")
// .addResourceLocations("file:/D:/fof/");
//
// }
//}
绝对路径是D:/fof/fof-video/xxx.mp4,前端sources中的src可以写成,
src: ‘/Path/fof-video/xxx.mp4’
2、 vue 前端ES6 require动态引入图片报错Error: Cannot find module“.”
如果使用require方式引入图片资源,则必须使用静态的字符串,不能使用变量,因为require是编译时执行的,而非运行时执行!因为require它是打包工具所需要的标识,搞成运行时通过变量去定义的话,它就没办法打包了
解决:而require里的正确的格式必须是path
可以这么写:
var imgUrl = "a";
let img = require('../images/'+imgUrl+'.jpg');
当然最好这么写:imgUrl 为图片名称即可,相对路径与绝对路径不能加。
var imgUrl = "b.jpeg";
let img = require('../images/'+imgUrl);
五、安装axios
cnpm install axios
配置请求拦截和响应拦截
request.js
import axios from 'axios'
// 引入qs模块,用来序列化post类型的数据
import qs from 'qs';
//应该是为了使用iview的message组件来做消息提示
// import {Message} from 'view-design'
// import {getToken, removeToken} from './util'
import router from '../router'
// import {getToken} from "./util";
import { message } from 'ant-design-vue'
let baseUrl = 'http://10.210.200.131:2525/'
// let baseUrl = process.env.BASE_API
// 多环境配置 环境的切换
// switch (process.env.NODE_ENV) {
// case 'development':
// // 这里是本地的请求url
// baseUrl = 'http://192.16.0.122:2424'
// break
// case 'production':
// // 生产环境url
// // baseUrl = $config.apiUrl.pro
// break
// }
/**
* 创建axios实例
* @type {AxiosInstance}
*/
const service = axios.create({
baseURL: baseUrl,
timeout: 30000
})
// request interceptor(请求拦截器)
service.interceptors.request.use(config => {
// const token = Vue.ls.get(ACCESS_TOKEN)
// const token = getToken()
// if (token) {
// config.headers['Authorization'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
// }
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
config.method === 'get' ?
config.params = {...config.params } : config.data = JSON.stringify({...config.data })
return config
}, error => {
return Promise.reject(error)
})
/**
* 响应结果处理
*/
// response interceptor(接收拦截器)
service.interceptors.response.use(
(response) => {
const res = response.data
if (res.code === 0 || res.code === 200) {
// 服务端定义的响应code码为0或者200时请求成功
// 使用Promise.resolve 正常响应
// console.log(Promise.resolve(res.result))
return Promise.resolve(res)
} else {
// debugger
// 使用Promise.reject 响应
message.error({ content: res.message })
return Promise.reject(res)
}
}, error => { //这里应该是把错误处理放进来了,没有单独写一个错误处理函数
let messages = ''
// debugger
if (error && error.response) {
console.log("error=>", error)
switch (error.response.status) {
case 401:
messages = '登录过期,请重新登录!'
// removeToken()
router.push("login")
const token = getToken()
console.log("*********token ", token)
break
case 403:
messages = error.response.data.path + ',' + error.response.data.msg
break
case 429:
messages = '访问太过频繁,请稍后再试!'
break
default:
messages = error.response.data.msg ? error.response.data.msg : '服务器错误'
break
}
message.error({ content: messages })
// 请求错误处理
return Promise.reject(error)
} else {
messages = '连接服务器失败'
message.error({ content: messages })
return Promise.reject(error)
}
}
)
export default service
六、安装vuex
cnpm install vuex –save
vuex适用于单页面应用,如果使用vue-router的以下方式:
const playUrl = this.$router.resolve({name:"videocontent",query: { currentVideo: JSON.stringify(currentVideo) }});
window.open(playUrl.href, '_blank');
打开新页面的时候,vuex存储的数据会被重置,这时如果想要实现在多个页面组件中使用到全局相同的数据,就可以使用cookie存储数据
七、安装ant-design-vue
npm install ant-design-vue --save
main,js
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css' // or 'ant-design-vue/dist/antd.less'
// 显示声明
Vue.use(Antd)
八、使用Moment.js
JavaScript 日期处理类库moment.js官网
1.安装模块
npm install moment --save
2.在main.js中引入
import moment from 'moment'; //导入模块
moment.locale('zh-cn'); //设置语言 或 moment.lang('zh-cn');
Vue.prototype.$moment = moment;//赋值使用
3.使用
this.$moment('2019/06/17 14:00:00').startOf('hour').fromNow(); //1小时前
this.$moment().format('YYYY年MM月DD日 HH时mm分ss秒'); //2019年08月01日 19时50分20秒
this.$moment(new Date()).format('YYYY年MM月DD日 HH时mm分ss秒'); //2019年08月01日 19时50分20秒
//计算两个日期的天数
let days = this.$moment('2019/06/17 14:00:00').diff(this.$moment('2019/06/20 14:00:00'), 'days');
//比较两个日期的大小
let flag = this.$moment('2019/06/17 14:00:00').isBefore('2019/06/17 14:00:00');
//比如ant design vue的table组件
{
title: '启动完成时间',
dataIndex: 'resetTime',
key: 'resetTime',
customRender: (text, row, index) => {
let time = this.$moment(text).format('YYYY-MM-DD HH:mm:ss')
return time
}
},