vue情况搭建相干先容

[复制链接]
发表于 2026-1-23 12:21:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、路由管理器阐明

  1. 1.route:译为路由,可以理解为单个路由或者某一个路由。
  2. 2.routes:路由集合,可以理解为多个route的集合。
  3. 3.router:路由器,可以理解为路由集合的管理者。例如,当我们在页面上点击某个按钮之后,router就会去routes中查找route,即路由管理者会去路由集合中寻找路由。
复制代码
二、路由依靠

  1. 在package.json文件中添加路由依赖
  2. "dependencies": {
  3.     "axios": "^0.18.0",
  4.     "vue": "^2.5.2",
  5.     "vue-router": "^3.0.1",
  6.     "element-ui": "^2.3.7",
  7.     "js-cookie": "^2.2.0",
  8.     "nprogress": "^0.2.0",
  9.     "vuex": "^3.0.1",
  10.     "echarts": "^4.2.0-rc.2",
  11.     "normalize.css": "^8.0.0",
  12.     "v-charts": "^1.19.0",
  13.     "v-distpicker": "^1.0.20"
  14.   },
复制代码
三、路由引入

  1. 在main.js中引入路由
  2. import Vue from 'vue'
  3. import App from './App'
  4. import router from './router'
  5. new Vue({
  6.   el: '#app',
  7.   router,
  8.   store,
  9.   components: { App },
  10.   template: '<App/>'
  11. })
复制代码
四、注册全局组件方式

  1. 如果需要把某一js文件注册为全局使用,则可以通过如下方式
  2. import tools from '@/utils/tools'  // 在main.js中引入文件
  3. Vue.prototype.$tools=tools;  //注册为全局变量
  4. this.$tools.openNewWindowOut(this.backLink);
复制代码
五、监听某个变量的厘革

  1. 示例:在我们通过ajax获取某个url请求地址,通过该url打开弹出式窗口或被拦截,原因:
  2.         当时用window.open()打开新浏览器窗口,如果这个url是通过ajax从后台获取,则会被浏览器拦截,因为浏览器监测到非用户行为打开新的浏览器窗口,认为这可能是广告或者不安全的操作;
  3. 怎么避免浏览器的这种拦截行为?
  4.         已说明这种拦截的情况是因为非用户操作产生的,因为可通过确认框由用户确认后打开,基于这种方式,我们可事先在vue页面绑定某个变量,当用户触发操作之后,把通过ajax获取的url变量赋给绑定的变量,在监测这个事先绑定的变量值的变化,具体实现如下:
  5. data(){
  6.         backUrl:'',
  7.         backLink:'',
  8. },
  9. methods:{
  10.         //  用户点击按钮
  11.         backClick(){
  12.           if(this.backUrl){
  13.             this.backLink = this.backUrl;
  14.           }else{
  15.             this.$message("请稍后,正在上架中....");
  16.           }
  17.      },
  18. },
  19. watch:{
  20.         // 方法名和变量名相同
  21.         backLink(){
  22.                  this.$tools.openNewWindowOut(this.backLink);
  23.           this.backLink = null;  //置空的原因:允许打开多个
  24.         }
  25. }
复制代码
六、路由守卫

  1. import router from './router'
  2. // 顶部进度条
  3. import NProgress from 'nprogress'
  4. // token文件导入
  5. import {getToken} from '@/utils/auth'
  6. import store from './store'
  7. import { Message } from 'element-ui'
  8. // 不授权就可以访问的页面
  9. const whitePageList = ['/login']
  10. /**
  11. * 路由守卫
  12. *    在路由守卫中,只有next()是放行,其它的如:next('/login'),next(to),next({...to,replace:true})都不是放行,而是中断当前导航,执行新的导航
  13. *  next('/login')说明:
  14. *    此含义并不是直接去/login路由,而是中断(中断指的是:不会执行router.afterEach(()=>{})),而是又进入一层路由守卫,这是to.path已经是新的路由,
  15. * 才执行next()放行。
  16. *    重点:在addRoutes()动态添加路由之后第一次访问被添加的路由,会出现白屏?
  17. *       这是因为刚刚addRoutes()完就立即访问,此时addRoutes()还没有执行结束,从而找不到刚添加的路由导致白屏,此时需要重新访问路由才可以。
  18. *    如何解决这种问题:
  19. *       使用next({..to,replace:true})来确保addRoutes()动态添加的路由已经完全被加载结束,
  20. *            replace:true 告诉Vue,本次操作之后,不能通过浏览器后退按钮,返回前一个路由,
  21. *       因此也可以直接写为:next(...to),作用为:如果参数to不能找到对应的路由之后,就再执行router.beforeEach(),直到能够找到对应的路由为止;这就意外着,
  22. * 如果能够找到对应的路由,那么addRoutes()就执行结束了,接下来会执行一次正确的路由,因此需要合适的设置next(),否则会进入死循环。
  23. */
  24. router.beforeEach((to,from,next)=>{
  25.   NProgress.start(); // 开始NProgress
  26.   // 获取token
  27.   if(getToken()){
  28.     if(to.path === '/login'){
  29.       next({path:'/'});
  30.       NProgress.done(); // 结束NProgress
  31.     }else{
  32.       // 如果用户角色列表长度为0,则获取用户信息,动态生成路由列表
  33.       if(store.getters.roles.length === 0){
  34.         store.dispatch('GetInfo').then(res=>{
  35.           let menus = res.data.menus;
  36.           let username = res.data.username;
  37.           store.dispatch('GenerateRoutes',{menus,username}).then(()=>{
  38.             router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表
  39.             next({ ...to, replace: true })
  40.           })
  41.         }).catch(error=>{
  42.           // 如果拉取用户信息出错,则登出重新登录
  43.           store.dispatch('FedLogOut').then(res=>{
  44.             Message.error(err || 'Verification failed, please login again');
  45.             next('/');
  46.           });
  47.         })
  48.       }else{
  49.         next();
  50.       }
  51.     }
  52.   }else{
  53.     // 如果没有登录,又不在白名单则直接放开
  54.     if(whitePageList.indexOf(to.path) != -1){
  55.       next();
  56.     }else{
  57.       next('/login');
  58.       NProgress.done(); // 结束NProgress
  59.     }
  60.   }
  61. })
  62. // 路由之后
  63. router.afterEach(()=>{
  64.   NProgress.done(); // 结束NProgress
  65. })
复制代码
七、拦截哀求和相应axios

  1. import axios from 'axios'
  2. import {Message,MessageBox } from 'element-ui'
  3. import store from "../store";
  4. import  {getToken} from "./auth";
  5. /**
  6. * axios介绍:
  7. *    简单的讲,就是发送get和set请求的
  8. *   拦截请求和响应
  9. *   转换请求和响应数据
  10. *   自动转换json等
  11. */
  12. //创建axios实例
  13. const service = axios.create({
  14.   baseURL:process.env.BASE_API,
  15.   timeout:15000 // 请求超时时间
  16. })
  17. // request请求拦截器
  18. service.interceptors.request.use(config=>{
  19.   // 在发送请求之前,判断token是否存在,如果存在,则把token添加到请求头header中
  20.   if(store.getters.token){
  21.     config.headers.Authorization = getToken();
  22.   }
  23.   return config;
  24. },error=>{
  25.   console.log(error);
  26.   /**
  27.    * Promise:异步操作对象序列化
  28.    *  Promise是一个对象,用于表示异步操作的成功或失败的结果,一般有三种状态:
  29.    *    pending:初始状态,既不代表成功,也不代表失败,
  30.    *    fulfilled:意外着操作成功完成,也可以称为resolved状态
  31.    *    rejected:意外着操作失败
  32.    *  pending状态的Peomise对象,可能触发fulfilled状态,并传递一个值给相应的状态处理方法;也有可能触发rejected状态并给相应的状态处理方法传递失败的值,
  33.    *  当出现上述任意一种状态时,Promise对象的then方法绑定的事件处理方法(handler)就会被调用(then方法的参数有两个:onfulfilled和onrejected,
  34.    *  并且都为Function类型,事件处理方法会根据不同的状态调用不同的方法)。
  35.    *
  36.    */
  37.   Promise.reject(error);
  38. })
  39. // response拦截器
  40. service.interceptors.response.use(response=>{
  41.   const res = response.data;
  42.   /**
  43.    * 判断返回值状态,如果为200-正常响应,401-未登录异常,否则为错误或异常响应
  44.    */
  45.   if(res.code !== 200){
  46.     Message({
  47.       message:res.message, // 错误响应的信息
  48.       type:"error", // 提示信息类型
  49.       duration:3 * 1000 //错误信息展示时间,单位为毫秒
  50.     });
  51.     if (res.code === 401 ){
  52.       MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录',
  53.         '确定登出',
  54.         {
  55.           confirmButtonText:'重新登录',
  56.           cancelButtonClass:'取消',
  57.           type:"error"
  58.       }).then(()=>{  // then作用:当then之前的语句被执行之后,再异步执行then内部的程序,可防止数据初始化失败造成的页面无法加载. 可多个连续使用
  59.         // 发送登出请求,重新载入当前页面
  60.         location.reload();
  61.       })
  62.     }
  63.     return Promise.reject('error');
  64.   }else{
  65.     return res;
  66.   }
  67. },error=>{
  68.   console.log('err'+error);
  69.   Message({
  70.     message:error.message, // 错误响应的信息
  71.     type:"error", // 提示信息类型
  72.     duration:3 * 1000 //错误信息展示时间,单位为毫秒
  73.   });
  74. })
  75. export default service
复制代码
八、多个组件共享某个状态Vuex

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import getters from './getters'
  4. import user from "./modules/user"
  5. import permission from "./modules/permission";
  6. /**
  7. * Vuex介绍:
  8. *    重点:多个组件共享某个状态
  9. *    Vuex是专门为vue.js开发的状态管理模式,它将集中存储管理应用中组件的状态,并用一定的规则保证状态朝着可预测的方向变化。
  10. *    store :仓库   state:状态
  11. *    VUE组件从store中读取状态,如果store中的状态发生变化,则相关的组件的状态将高效的更新。
  12. *    不能直接改变store中的state(状态),改变的方式只能是显式的提交(commit),方便跟踪某个状态的变化
  13. *  触发状态变更方式:store.commit('increment')
  14. *
  15. *
  16. *  this.$store.dispatch('isLogin', true):异步操作,数据提交至 actions ,可用于向后台提交数据
  17. *  this.$store.commit('loginStatus', 1):同步操作,数据提交至 mutations ,可用于登录成功后读取用户信息写到缓存里
  18. *  虽然提交的方式不同,但都是传值个vuex的mutation,进而改变state
  19. */
  20. Vue.use(Vuex);
  21. const store = new Vuex.Store({
  22.   modules: {user,permission},
  23.   getters
  24. })
  25. export default store
复制代码
  1. /**
  2. * Vuex中Getters的说明:
  3. *    store(容器)中的state派生状态的管理
  4. *    Getters可以认为是store的计算属性,其返回值会根据依赖缓存,并且只有依赖值发生变化后才会重新计算
  5. *    对外暴露的公共接口为:store.getter
  6. */
  7. const getters = {
  8.   sideBar: state => state.app.sideBar,
  9.   // 设备
  10.   device:state => state.app.device,
  11.   // 客户端缓存的用户名
  12.   token:state => state.user.token,
  13.   // 用户头像
  14.   avatar: state => state.user.avatar,
  15.   // 用户名
  16.   name: state => state.user.name,
  17.   // 登录用户所属角色
  18.   roles: state => state.user.roles,
  19.   // 动态路由设置
  20.   addRouters: state => state.permission.addRouters,
  21.   routers: state => state.permission.routers
  22. }
  23. export default getters
复制代码
  1. import {getToken,setToken,removeToken} from "../../utils/auth"
  2. import {login,loginOut,getInfo} from "../../api/login";
  3. /**
  4. * Vuex中各参数说明
  5. *  state:
  6. *    单一状态树,此状态树包含整个应用层级会话的状态,
  7. *  mutations:
  8. *    更改store容器中的状态的唯一方式就是提交mutation(突变),每一个mutation都有一个type(类型)和handler(回调函数),这个handler就是我们
  9. *  实际进行state更改的地方,并且会接收state作为第一个参数,特别注意的是,每个mutation必须是同步函数,其原理为:在回调函数中进行的状态更新是不了追踪的。
  10. *  actions:
  11. *    前面说明,为了所有的应用层级别的会话状态的更新都是可追踪的,所以引入了只能进行同步操作的mutations,但是在vuex中,也引入了能进行一步操作的actions,
  12. *  Actions包含任何的异步操作,虽然提交的是Mutation,但却不是直接更改状态。
  13. *
  14. */
  15. const user = {
  16.   state:{
  17.     // 本地token
  18.     token:getToken(),
  19.     // 用户名
  20.     name:'',
  21.     // 头像
  22.     avatar:'',
  23.     // 所属角色组
  24.     roles:[]
  25.   },
  26.   mutations:{
  27.     SET_TOKEN:(state,token)=>{
  28.       state.token = token;
  29.     },
  30.     SET_NAME:(state,name)=>{
  31.       state.name = name;
  32.     },
  33.     SET_AVATAR:(state,avatar)=>{
  34.       state.avatar = avatar;
  35.     },
  36.     SET_ROLES:(state,roles)=>{
  37.       state.roles = roles;
  38.     }
  39.   },
  40.   actions:{
  41.     // 登录
  42.     Login({commit},userInfo){
  43.       const userName = userInfo.userName.trim();
  44.       return new Promise((resolve,reject)=>{
  45.         login(userName, userInfo.passWord).then(response=>{
  46.           const data = response.data;
  47.           const tokenHeader = data.tokenHead + data.token;
  48.           setToken(tokenHeader);
  49.           // 提交突变状态
  50.           commit('SET_TOKEN',tokenHeader);
  51.           resolve();
  52.         }).catch(error=>{
  53.           reject(error);
  54.         })
  55.       })
  56.     },
  57.     // 获取用户信息
  58.     GetInfo({commit},state){
  59.       return new Promise((resolve,reject)=>{
  60.         getInfo().then(response=>{
  61.           const data = response.data;
  62.           if(data.roles && data.roles.length > 0){
  63.             commit('SET_ROLES',data.roles);
  64.           }else{
  65.             reject('getInfo: roles must be a non-null array !');
  66.           }
  67.           commit('SET_NAME',data.username);
  68.           commit('SET_AVATAR',data.icon);
  69.           resolve(response)
  70.         }).catch(error=>{
  71.           reject(error);
  72.         })
  73.       });
  74.     },
  75.     // 后台登出
  76.     LogOut({commit},state){
  77.       return new Promise((resolve, reject) => {
  78.         loginOut().then(response=>{
  79.           const data = response.data;
  80.           // 突变会话级别的变量
  81.           commit('SET_TOKEN','');
  82.           commit('SET_ROLES',[]);
  83.           // 删除本地token
  84.           removeToken();
  85.           // 成功响应
  86.           resolve();
  87.         }).catch(error=>{
  88.           reject(error)
  89.         })
  90.       });
  91.     },
  92.     // 前端登出
  93.     FedLogOut({commit},state){
  94.       return new Promise((resolve, reject) => {
  95.         commit('SET_TOKEN', '')
  96.         removeToken()
  97.         resolve()
  98.       });
  99.     }
  100.   }
  101. }
  102. export default user
复制代码
九、vue中svg的组件

  1. import Vue from 'vue'
  2. import SvgIcon from '@/components/SvgIcon'// svg组件
  3. // 全局注册
  4. Vue.component('svg-icon', SvgIcon)
  5. const requireAll = requireContext => requireContext.keys().map(requireContext)
  6. /* require.context("./test", false, /.test.js$/);
  7.     这行代码就会去 test 文件夹(不包含子目录) 下面的找所有文件名以 .test.js 结尾的文件能被 require 的文件。
  8.     更直白的说就是 我们可以通过正则匹配引入相应的文件模块。
  9.      require.context有三个参数:
  10.      directory:说明需要检索的目录
  11.      useSubdirectories:是否检索子目录
  12.      regExp: 匹配文件的正则表达式
  13. */
  14. const req = require.context('./svg', false, /\.svg$/)
  15. requireAll(req)
复制代码
  1. <template>
  2.   <svg :class="svgClass" aria-hidden="true">
  3.     <use :xlink:href="iconName"></use>
  4.   </svg>
  5. </template>
  6. <script>
  7. export default {
  8.   name: 'svg-icon',
  9.   props: {
  10.     iconClass: {
  11.       type: String,
  12.       required: true
  13.     },
  14.     className: {
  15.       type: String
  16.     }
  17.   },
  18.   computed: {
  19.     iconName() {
  20.       return `#icon-${this.iconClass}`
  21.     },
  22.     svgClass() {
  23.       if (this.className) {
  24.         return 'svg-icon ' + this.className
  25.       } else {
  26.         return 'svg-icon'
  27.       }
  28.     }
  29.   }
  30. }
  31. </script>
  32. <style scoped>
  33. .svg-icon {
  34.   width: 1.2em;
  35.   height: 1.2em;
  36.   vertical-align: -0.18em;
  37.   fill: currentColor;
  38.   overflow: hidden;
  39. }
  40. </style>
复制代码
十、passive和prevent区别

  1. W3C规定,当一个from元素中只有一个输入框时,在该输入框中按下回车键该表单应该提交,如果希望阻止这一默认的行为,
  2.         则需要在<el-from>标签上加上@submit.native.prevent.
  3.             native:把一个vue组件转化为一个普通的HTML标签,并且该修饰符对普通HTML标签是没有任何作用的。
  4.             prevent:阻止某些标签默认拥有的事件,如a[href="#"],button[type="submit"],这类标签会在冒泡结束后自动执行默认事件,
  5.             passive:通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,
  6.         不用查询了,我们没用preventDefault阻止默认动作。
  7.              ** passive和prevent冲突,不能同时绑定在一个监听器上
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表