IT教程 ·

vue项目实战经验汇总

目次

  • 1.vue框架运用注重事项和履历
    • 1.1 处理Vue动态路由参数变化,页面数据不更新
    • 1.2 vue组件里定时器烧毁问题
    • 1.3 vue完成按需加载组件的两种体式格局
    • 1.4 组件之间,父子组件之间的通讯计划
    • 1.5 vue中 $event 的用法--猎取当前父元素,子元素,兄弟元素
    • 1.6 vue常用工具函数总结
    • 1.7 axios二次封装http要求
  • 2.elementui组件修正履历总结
    • 2.1 element-ui 中步骤条的深度运用
    • 2.2 v-loading框中的提醒笔墨换行
    • 2.3 路由菜单项双击控制台报错
  • 3.Vue项目设置
    • 3.1 Vue-cli3 设置开发、生产和测试环境
    • 3.2开发环境中代办的切换设置

1.vue框架运用注重事项和履历

本文重要总结了在开发vue项目中的一些实践履历和踩过的一些坑,后续会接着更新,便于后期复盘,愿望也对你有所协助

1.1 处理Vue动态路由参数变化,页面数据不更新

问题形貌:

碰到动态路由如:/page/:id
从/page/1 切换到 /page/2 发明页面组件没有更新

处理体式格局:
给<router-view :key="key">增添一个差别:key值,如许vue就会辨认这是差别的 了。

<router-view :key="key"></router-view>
  ...
  computed:{
        key(){
            return this.$route.path + Math.random();
        }
    }

1.2 vue组件里定时器烧毁问题

问题形貌:
在a页面写一个定时器,每秒钟打印一次,然后跳转到b页面,此时能够看到,定时器依旧在实行。
引荐的处理体式格局:
经由过程$once这个事宜侦听器器在定义完定时器以后的位置来消灭定时器。

const timer = setInterval(() => {
    // 定时器操纵
}, 1000)

// 经由过程$once来监听定时器,在beforeDestroy钩子能够被消灭。
this.$once('hook:beforeDestroy', () => {            
    clearInterval(timer);                                    
})

1.3 vue完成按需加载组件的两种体式格局

1.运用resolve => require(['./ComponentA'], resolve),要领以下:

const ComponentA = resolve => require(['./ComponentA'], resolve)
  1. 运用 () => import(), 详细代码以下:
const ComponentA = () => import('./ComponentA')

1.4 组件之间,父子组件之间的通讯计划

组件之间的通讯计划:

  • 经由过程事宜总线(bus),即经由过程宣布定阅的体式格局
  • vuex
  • 父子组件:
  • 父组件经由过程prop向自组件通报数据
  • 子组件绑定自定义事宜,经由过程this.$emit(event,params) 来挪用自定义事宜
  • 运用vue供应的$parent/$children & $refs要领来通讯
  • provide/inject
  • 深层次组件间的通讯 $attrs, $listeners

 

1.5 vue中 $event 的用法--猎取当前父元素,子元素,兄弟元素

<button @click = “fun($event)”>点击</button>
  ...
  
  methods: {
   fun(e) {
    // e.target 是你当前点击的元素
    // e.currentTarget 是你绑定事宜的元素
    #取得点击元素的前一个元素
    e.currentTarget.previousElementSibling.innerHTML
    #取得点击元素的第一个子元素
    e.currentTarget.firstElementChild
    # 取得点击元素的下一个元素
    e.currentTarget.nextElementSibling
    # 取得点击元素中id为string的元素
    e.currentTarget.getElementById("string")
    # 取得点击元素的string属性
    e.currentTarget.getAttributeNode('string')
    # 取得点击元素的父级元素
    e.currentTarget.parentElement
    # 取得点击元素的前一个元素的第一个子元素的HTML值
    e.currentTarget.previousElementSibling.firstElementChild.innerHTML
  
    }
        },

1.6 vue常用工具函数总结

/*
 日期相干 dateFormater:格式化时候
 timestampToTime
 * */
function dateFormater(formater, t){
   let date = t ? new Date(t) : new Date(),
      Y = date.getFullYear() + '',
      M = date.getMonth() + 1,
      D = date.getDate(),
      H = date.getHours(),
      m = date.getMinutes(),
      s = date.getSeconds();
   return formater.replace(/YYYY|yyyy/g,Y)
      .replace(/YY|yy/g,Y.substr(2,2))
      .replace(/MM/g,(M<10?'0':'') + M)
      .replace(/DD/g,(D<10?'0':'') + D)
      .replace(/HH|hh/g,(H<10?'0':'') + H)
      .replace(/mm/g,(m<10?'0':'') + m)
      .replace(/ss/g,(s<10?'0':'') + s)
}
//  dateFormater('YYYY-MM-DD HH:mm', 1580787420000)//==> "2020-02-04 11:37"
// dateFormater('YYYYMMDDHHmm', new Date()) //==> 201906261830

/*
猎取Url参数,返回一个对象
 * */
function GetUrlParam(){
   let url = document.location.toString();
   let arrObj = url.split("?");
   let params = Object.create(null)
   if (arrObj.length > 1){
      arrObj = arrObj[1].split("&");
      arrObj.forEach(item=>{
         item = item.split("=");
         params[item[0]] = item[1]
      })
   }
   return params;
}
// ?a=1&b=2&c=3 ==> {a: "1", b: "2", c: "3"}

//toFullScreen:全屏
function toFullScreen(){
   let elem = document.body;
   elem.webkitRequestFullScreen
   ? elem.webkitRequestFullScreen()
   : elem.mozRequestFullScreen
   ? elem.mozRequestFullScreen()
   : elem.msRequestFullscreen
   ? elem.msRequestFullscreen()
   : elem.requestFullScreen
   ? elem.requestFullScreen()
   : alert("浏览器不支持全屏");
}

//exitFullscreen:退出全屏
function exitFullscreen(){
   let elem = parent.document;
   elem.webkitCancelFullScreen
   ? elem.webkitCancelFullScreen()
   : elem.mozCancelFullScreen
   ? elem.mozCancelFullScreen()
   : elem.cancelFullScreen
   ? elem.cancelFullScreen()
   : elem.msExitFullscreen
   ? elem.msExitFullscreen()
   : elem.exitFullscreen
   ? elem.exitFullscreen()
   : alert("切换失利,可尝试Esc退出");
}

1.7 axios二次封装http要求

import axios from 'axios'
import router from '@/router'
import {removeSessionStorage} from './storage';
import Vue from 'vue'
import { Message } from 'element-ui' // 援用element-ui的加载和音讯提醒组件
// 要求超时时候设置
axios.defaults.timeout = 30000;
// api地点设置
axios.defaults.baseURL = "";
// console.log(process.env.VUE_APP_BASE_API)
Vue.prototype.$http = axios
// 在全局要乞降相应拦截器中增加要求状况
let loading = null

// 要求拦截器
axios.interceptors.request.use(
    config => {
      config.headers = {
        'Content-Type': 'application/json'
      };
      // loading = Loading.service({ text: '冒死加载中' })
      let token = sessionStorage.getItem('-_token_-');
      if (token) {
        config.headers['token'] = token;
      }
      return config
    },
    error => {
      return Promise.reject(error)
    }
)

// 相应拦截器
axios.interceptors.response.use(
    response => {
      if (loading) {
        loading.close()
      }
      //console.log(response)
      const code = response.status
      if ((code >= 200 && code < 300) || code === 304) {
        let errorCode = response.data.errCode;
        if(errorCode==='000000'){
          return Promise.resolve(response.data)
        }else {
          if (errorCode === 'SYS0404') {
                router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '您要求的资本找不到(毛病码:404) ',
              },
            });
          } else if (errorCode === 'SYS0401') {
            removeSessionStorage('-_token_-');
            router.replace({
              path: '/login',
              query: {
                redirect: router.currentRoute.fullPath
              }
            });
          }
          // Message.error(response.data.message)
          return Promise.resolve(response.data)
        }
        // return Promise.resolve(response.data)
      } else {
        return Promise.reject(response)
      }
    },
    error => {
      if (loading) {
        loading.close();
      }
      console.log(error);
      if (error.response) {
        switch (error.response.status) {
          case 401:
          case 403:
            // 返回401 消灭token信息并跳转到上岸页面
            removeSessionStorage('-_token_-');
            router.replace({
              path: '/login',
              query: {
                redirect: router.currentRoute.fullPath
              }
            });
            break;
          case 404:
            Message.error('收集要求不存在');
            console.log('毛病码:404 路由跳转 currentRoute  %o ', router.currentRoute.path);
            router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '您要求的资本找不到(毛病码:404) ',
              },
            });
            break;
          case 502:
            router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '网关毛病(毛病码:502),请联络体系管理员 ',
              },
            });
            break;
          default:
            Message.error(error.response.data.message ||'体系失足,请联络体系管理员(毛病码:'+error.response.status+')!');
        }
      } else {
        let controlParam = {
          desc: '',
          path: router.currentRoute.path,
          isTimeout: false,
        };
        // 要求超时或许收集有问题
        if (error.message.includes('timeout')) {
          Message.error('要求超时!请搜检收集是不是一般');
          controlParam.desc = '收集断开,请搜检您的收集 ';
          controlParam.isTimeout = true;
        } else {
          Message.error('要求失利,请搜检收集是不是已衔接');
          controlParam.desc = '页面加载失利 ';
        }
        router.push({
          name: 'error',
          params: controlParam,
        });
      }
      return Promise.reject(error);
    }
);

2.elementui组件修正履历总结

2.1 element-ui 中步骤条的深度运用

2.1.1element-UI的操纵步骤steps每一项增加事宜,比方click,hover

<el-steps :space="200" :active="1" finish-status="success">
  <el-step @click.native="on_click(1)" title="已完成"></el-step>
  <el-step @click.native="on_click(2)" title="举行中"></el-step>
  <el-step @click.native="on_click(3)" title="步骤 3"></el-step>
</el-steps>

2.1.2 详细营业交互

2.1.3 转变笔墨方向

变成

调解css,设置magin和background

.el-step__main {
    white-space: normal;
    text-align: left;
    margin-top: -31px;
    margin-left: 25px;
}

}
i
.el-step__title {
    font-size: 16px;
    line-height: 38px;
    background: #FFF;
    width: 50px;
    position: relative;
    z-index: 1;
}

2.2 v-loading框中的提醒笔墨换行

 

2.3 路由菜单项双击控制台报错

//处理菜单双击报错
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

3.Vue项目设置

3.1 Vue-cli3 设置开发、生产和测试环境

  • 建立开发环境变量 .env.development
  • 建立生产环境变量 .env.production
  • 建立测试环境变量 .env.test

注重环境变量的前缀必需是VUE_APP

在其他文件中经由过程process.env.VUE_APP_BASE_API来访问,例如在接口文件代码中

import axios from 'axios'
import router from '@/router'
// 要求超时时候设置
axios.defaults.timeout = 30000;
// api地点设置
axios.defaults.baseURL = "process.env.VUE_APP_BASE_API";

对应的package.json设置为

"scripts": {
  "serve": "vue-cli-service serve --mode development",
  "build": "vue-cli-service build --mode production",
  "test": "vue-cli-service build --mode test",
  },

3.2开发环境中代办的切换设置

为了应对如许的跨域场景,在代码开发时,devServer要代办到当地后端,测试时,又要去修正代办到测试环境,上线后,调试新问题有大概代办到线上环境

对vue.config.js的举行设置

const Timestamp = new Date().getTime();  //当前时候为了防备打包缓存不革新,所以给每一个js文件都加一个时候戳
const proxyTargetMap = {
    prod: 'https://xxx.xxx.com/',
    dev: 'http://192.168.200.230:6379',
    test: 'http://test.xxx.com',
    local: 'http://localhost:8080/'
}
let proxyTarget = proxyTargetMap[process.env.API_TYPE] || proxyTargetMap.local
module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',
    outputDir: 'dist',
    assetsDir: 'static',
    lintOnSave: false, // 是不是开启eslint保留检测
    productionSourceMap: false, // 是不是在构建生产包时生成sourcdeMap
    // 调解内部的 webpack 设置。
    chainWebpack: () => { },
    //configureWebpack 这部份打包文件增加时候戳,防备缓存不更新
    configureWebpack: {
        output: { // 输出重构  打包编译后的 文件称号  【模块称号.版本号.时候戳】
            filename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`,
            chunkFilename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`
        },
    },

    devServer : {
        proxy: {
            '/api' : {
                target: proxyTarget,
                changeOrigin: true,
                pathRewrite: {
                    '^/api' : ''
                }
            }
        }
    }
};

对应的package.json设置为

"scripts": {
  "serve": "vue-cli-service serve --mode development",
+  "serve:dev": "cross-env API_TYPE=dev vue-cli-service serve --mode development",
+  "serve:test": "cross-env API_TYPE=test vue-cli-service serve --mode development",
  "build": "vue-cli-service build --mode production",
  "test": "vue-cli-service build --mode test",
  },

参与评论