欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端开发笔记,持续更新中!!!

程序员文章站 2022-05-11 11:06:18
...

# reduce 函数

// 求和
var numbers=[65,44,12,4];
function getSum(total,num){
    retuen total+num
}
function MyFun(item){
    var numrs=numbers.reduce(getSum)
}

#Object.keys()方法

//获得对象中所有的键或者其他方法使用
//PS:IE11包括IE11不支持
var person = {
    name:"张三",
    age:18,
    66:"55"
};
Object.keys(person);//["66","name","age"]
Object.values(person);//["55","张三",18];
/*
* 如果属性名的类型是Number,那么Object.keys返回值是按照key从小到大的顺序排列
* 如果属性名的类型是String,那么Object.keys返回值是按照树形被创建的时间升序排列
* 如果属性名的类型是Symbol,那么逻辑和String的逻辑相同
*/

# vue 的router.addRoutes 方法

router.addRoutes -----函数签名

router.addRoutes(routes:Array) — 动态添加路由规则,参数必须是符合routes选项要求的数组

  1. 基本使用

    //现在有一个非常普通的路由
    const routes = [
        {
            path:"/",
            name:"Home",
            component:Home
        },
        {
            path:"PageA",
            name:"PageA",
            conponent:PageA
        }
    ]
    const router = new VueRouter({
        routes
    })
    export default router;
    
    那么使用router.addRoutes改造上面的配置,实现动态添加PageA,如下
    const router = new VueRouter({
        {
        	path:"/",
        	name:"Home",
        	component:Home
    	}
    });
    let route = [
        {
            path:"PageA",
            name:"PageA",
            component:PageA
        }
    ];
    router.addRoutes(route);
    export default router;
    // 把原来的routes配置照搬到一个新的数组中,就可以作为addRoutes的参数使用,经验证实,通过addRoutes动态配置和普通配置一样
    

    2.路由的权限验证

    如果网页有[管理员,普通用户,其他管理]等多种角色,不同的角色看见的页面页是不同的,比如普通用户不应该看见管理员的控制台,那么这个时候,动态路由就非常有用了,

let PageA,pageB,pageC;
let route = [
    {
        path:"/PageA",
        name:"PageA",
        component:PageA
    },
    {
        path:"/PageB",
        name:"PageB",
        component:PageB
    },
    {
        path:"/PageC",
        name:"PageC",
        component:PageC
    }
];
let commOnUser=["PageA","PageB"];
let commInUserRoute=route.filter(function(page){
    return commOnUser.includes(page.name)
})
console.log(commInUserRoute);
router.addRoues(commInUserRoutes);
//结果
/*
*	(2) [{...},{...}]
*	0:{path:"/PageA",name:"PageA",component:PageA},
*	1:{path:"/PageB",name:"PageB",component:PageB},
*	length:2
*/
//这样就可以完成权限验证,当前如果权限在前台验证会有一定的安全隐患,最好的还是在后台来进行限制访问

PS:router.addRoutes 之后的next() 可能会失效,因为可能next() 的时候路由并没有完全add完成

解决办法:**通过next(to)**解决,这行代码重新进入router.beforeEach这个钩子,这是后再通过 **next()**来释放钩子,这能确保所有的路由都已经挂载完成了

#封装请求和vuex && 路由守卫

1.封装axios请求,设置请求拦截器和响应拦截器

import axios from "axios";
//引入页面上方的进度条
import Nprogress from "nprogress";//需要自己去npm安装环境
import "nprogress/nprogress.css";
const Axios=axios.create({
 baseUrl:"";
 withCredentials:fasle,//请求头需要携带cookies的话,需要设置为true、否则false或者不写
 timeout:5000//请求超时的时间(毫秒),服务器在该时间没有响应会直接超时,执行自己设置超时的事件
})
//请求拦截器,所有的请求都会触发该事件
Axios.interceptors.request.use(
	config => {
     Nprogress.start();
     if (sessionStorage.getItem("token")) {
        	config.headers.token=sessionStorage.getItem("token")
        }
     retuen config
 },
 error => {
     Promise.reject(error)
 }
);
//响应拦截器,所有请求回来的数据都会触发该事件
Axios.interceptors.response.use(
	res => {
     Nprogress.done();
     return res
 },
 error => {
     Nprogress.done();
     //如果请求超时了,对请求超时的处理
     if (error.message,includes("timeout")) {
				console.error("请求超时")
         }
 }
)
export default Axios;//将自己定义的Axios抛出去,方便其他事件引用

2.开始封装xaios请求

在src下创建一个api的文件夹,在里面创建对应的事件

import axios from "@/neteork/axiosUtil";//自己封装axios请求的位置
//登录的封装请求
export function login (data) {
 return axios({
     url:"/api/login",//自己需要请求的地址
     method:"post",//请求的方式,
     data//原来是data:data,可以简写为data
 })
}
//登出的请求
export function loginOut () {
 return axios({
     url:"/api/loginOut",
     method:"post"
 })
}
//获取侧拉菜单
export function getmenu (userCode) {
 return axios({
     url:"/api/menu",
     method:"get",
     params:{userCode}
 })
}

3.登录和登出基本是靠着token去控制的,所以用到好多,封装下token

//我将所有封装事件在src下创建了一个util文件夹,将所有的封装事件封装在里面
//token.js
const tokenKey=sessionStorage.getItem("token") || undefined;
export function setToken (token) {
 return sessionStorage.setItem("token",token);
}
export function getToken () {
 return sessionStorage.getItem("token")
}
export function removeToken () {
 return sessionStorage.removeItem("token")
}

4.在vuex中封装请求

/*
*	在store的文件下创建一个modules文件夹
*	创建user.js文件
*/
//引入封装好的请求
import {login, loginOut, getmenu} from "@/api/user";
//引入关于token的封装
import {getToken, setToken, removeToken} from "@/utils/auth";
const state = {
 token: getToken,//登录够需要存储的token
 name: "",//登录人的用户名
 menus: [],
 userCode: "",//当前登录人的标识码(登录的账号)
 loginF: false,//双层控制是否登录,true代表登录了,false代表没登录
};
const mutations = {
 setToken (state,token) {
     state.token = token;
 },
 setName (state,name) {
     state.name = name;
 },
 setMenu (state,menu) {
     state.menus = menu;
 },
 setUserCode (state,userCode) {
     state.userCode = userCode;
 },
 setLoginF (state,loginF) {
     state.loginF = loginF;
 }
};
const actions = {//所有的ajax请求或者异步事件都在这里面处理
 //用户登录触发的事件
	login ({commit}, menu) {//userInfo事件传递过来的参数
     const { userCode, password} = userInfo;
     return new Promise ((resolve,reject) => {
         login({userCode,password})
         .then(res => {
             const {data} = res;
             commit("setToken",data.token);
             commit("setLoginF",true);
             setToken(data.token);
             resolve();
         })
         .catch(err => {
             reject(err)
         })
     })
 },
 //登录成功后请求侧拉菜单的事件
 getmenu ({commit}, state) {
     retuen new Promise((resolve,reject) => {
         getmenu(state.userCode)
         .then(res => {
             const {data} =res;
             commit("setMenu", data);
             resolve();
         })
         .catch(err => {
             rejece(err)
         })
     })
 },
 //登出的事件
	loginOut ({commit,state}) {
     return new Promise((resolve,reject) => {
         loginOut(state.userCode)
         .then(res => {
            	commit("setToken","");
             commit("setMenu",[]);
             commit("setLoginF",false);
             removeToken();
             resolve();
         })
         .catch(err => {
             reject(err)
         })
     })
 },
 //移除token和菜单和session
 resetToken ({commit}) {
     return new Promise(resolve => {
         commit("setToken","");
         commit("setMenu",[]);
         commit("setLoginF",fasle);
         removeToken();
         resolve();
     })
 }
};
export default {
 namespaced: true,
 state,
 mutataions,
 actions
};

5.在store根文件下创建一个getters.js

//该文件主要让用户直接获取数据用
const getters = {
 token: (state) => {
     state.user.token
 },
 name: (state) => {
     state.user.name
 },
 menus: (state) => {
     state.user.menus
 },
 userCode: (state) => {
     state.user.userCode
 },
 loginF: (state) => {
     state.user.loginF
 }
};
export default getters;

6.在主文件store.js里面处理事件

import Vue from "vue";
import Vuex from "vuex";
import getters frm "./getters";//引入刚才创建的getters文件

Vue.use(Vuex);

const modulesFiles = require.context("./modules", true, /\.js$/);
//不需要将mudules里面封装的vuex在本文件挨着import进来了
//通过本事件处理
const modules = modulesFiles.keys().reduce((modules,modulePath) => {
 //设置将 xx.js 文件设置为 "xx“
 const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/,"$1");
 const value = modulesFiles(modulePath);
 modules[moduleName] = value.default;
 return modules
},{});
const store = new Vuex.Store({
 modules,
 getters
})
export default store;
//----------------------------------------------------------------
//另外一种写法,挨着把文件引入
import Vue from "vue";
import Vuex from "vuex";
import getters frm "./getters";//引入刚才创建的getters文件
import user from "./modules/user";
Vue.use(Vuex);
export default new Vuex.Store({
 modules:{
     user,
     getters
 }
})

7.随后配置路由守卫

//在src文件夹下创建perminnion.js文件
import router from "./router";//router是router配置的文件夹
import store from "./store";
import {Message} from "element-ui";//引入elemen-ui的message组件,可以进行相应的提示
import Npogress from "nprogress";
import "nprogress/nprogress.css";
import {getToken} from "@/utils/auth";
Npogress.configure({showSpinner: false});
router.beforeEach(async (to,from,next) => {
 Npogress.start();
 document.title=to.meta.title;//每个路由都配置的title
 //如果跳转的页面没有,就跳转404页面
 if(to.matched.length === 0) {
   	next("/404");//自己定义的404页面 	
   }
 //校验是否登录,防止部登录,直接进入其他页面
 const HasToken = getToken();//获取token
 const HasLoginF = store.getters.loginF;//获取是否登录
	if(HasToken && HasLoginF){
    	if (to.path === "/login") {
         	next({path:"/home"});//项目设置的首页
         	Npogress.done();
         }else if (to.meta.requireAuth) {
                   	next()
                   }else{
                       next({
                           path: "/login",
                           query: {
                               redirect: to.fullPath
                           }
                       })
                   }
    }else {
        next({
            path:"/login",
            query: {
                redirect: to.fullPath
            }
        })
    }
})

8.登录触发的事件

//因为登录页面可能是从别的页面打回来的,所以在登录页面加一个watch监视路由
watch: {
$route: {
   handler: function (route) {
       const query=route.query;
       if (query) {
        	 this.redirect = query.redirect  	 	
        }
   },
   immediate: true
}  
};
//PS:记得在data中定义redirect:undefinde
//在登录界面点击登录的时候触发封装的事件
this.$store.dispatch("user/login",this.regForm)
.then(res => {
 this.$store.dispatch("user/getmenu",this.regForm.userCode)
 .then(res => {
     this.$router.push({
         path:this.redirect || "/home"
     })
 })
 .catch(err => {
     Promise.reject(err);
 })
})

9.注销触发的事件

logOut () {
 this.$store.dispatch("user/logOut")
 this.$router.push(`/login?redirect=${this.$route.fullPath}`)
}

# watch 初始化不会触发事件问题

//可以添加immediate 属性,这样初始化的时候也同样会触发
watch: {
    searchText: {
        handler: function (newValue, oldValue) {
            //newValue是新数据,oldValue是老数据
            console.log(newValue,oldValue);
        },
        immediate: true//第一次刷新页面的时候就会执行
    }
}

# vue报错Do not use built-in or reserved HTML elements as component id

 // 一版情况是因为组件命名和引入的不知道导致的
export default {
    name:"header"
}
//在组件引入上方组件的时候,将引入的名字需要和name名称保持一致
 import header from "./header" //名称保持一致
/*
* 还有一种情况是名称哟两个大写的英文单词书写造成的
import TestPage from "./TestPage"
*/
//使用的时候
//		<div>
//			<testpage></textpage>
//		</div>
//改使用标签即可
//		<div>
//			<test-page></text-page>
//		</div>

# 在vue中用v-for给src动态绑定图片不显示问题

//用v-for给图片的img动态绑定本地的src属性
						<div
							class="img_carousel"
							v-for="(items, indexs) in item.carousel"
							:key="indexs"
						>
							<img :src="imgSrc(items)" alt="加载失败" />
						</div>
//设置imgSrc事件,将当前本地的图片名字传入,通过事件将图片路径完整的返回
//然后在methods中设置imgSrc事件
methods:{
    imgSrc(item){
        //拼接路径,将路径return出去
        return require(`../assets/carousel/${item}`)
    }
}

# el的日期组件

//element ui 的日期组件,选择区间日期和具体时间
					<el-date-picker
						v-model="userDeatil.Time"
						type="datetimerange"
						start-placeholder="开始时间"
						end-placeholder="结束时间"
						:default-time="['12:00:00', '08:00:00']"
						size="small"
						value-format="yyyy-MM-dd HH:mm:ss"
					></el-date-picker>
// 注意,把选择的去掉一次后,绑定的参数值直接为null

# webpack打包vue项目后,head里面有特别多的link(ref=prefetch和ref=preload)

这种加载影响了加载速度,加载了太多不需要的东西,所以需要优化

// 通过配置wenpack去掉这一种行为
module.export = {
    chainWebpack(config) {
		config.plugins.delete("prefetch");
		config.plugins.delete("preload");
	}
}

然后再次运行项目,就会发现,多余的都去掉了