0
点赞
收藏
分享

微信扫一扫

Vue 实战篇

王老师说 2022-03-20 阅读 119
vue.js前端

一、Ant Design Pro 介绍

1、访问地址:https://pro.ant.design/zh-CN/

2、开箱即用的中台前端/设计解决方案

二、使用Vue CLI3快速创建项目

1、创建步骤:
vue create ant-design   依据需要选择相应的依赖

cd ant-design   打开项目文件

npm i ant-design moment  安装项目中的依赖,依据moment时间安装
2、自定义Webpack和babel配置
依据 vue CLI 相关 webpack 配置进行对 vue.config.js 进行修改

ant-design-vue 组件库的按需加载   在babel.config.js文件中加入下面代码:

{
  "plugins": [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
  ]
}
3、设计一个高扩展性的路由

公共页面设计统一引入 的挂载项 的三种方式:

(1)、通过公共组件的形式引入

Header.vue 组件中:

<template>
    <div>
        //即将相应的页面在此显示
        <router-view></router-view>
    </div>
</template>

import Header from '@/src/components/header/index'

export default new Router({

    mode:'history',
    base:process.env.BASE_URL,
    routes:[
        {
            path:'/user',
            component: Header,
            children:[
                {
                    path:'/user/login',
                    name:'login',
                    component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
                }
            ]
        }
    ]
})

(2)、通过render函数的形式引入

export default new Router({

    mode:'history',
    base:process.env.BASE_URL,
    routes:[
        {
            path:'/user',
            component: { render: h => h('router-view')},
            children:[
                {
                    path:'/user/login',
                    name:'login',
                    component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
                }
            ]
        }
    ]
})

(3)、通过layout文件的形式引入带样式的 挂载项

新建的layout 文件夹中的 index.vue 组件 书写样式

<template>
    <div>
        //即将相应的页面样式在此显示
        <div> Ant Design Vue</div>
        <div>公用头部样式</div>
        <router-view></router-view>
    </div>
</template>

import Header from '@/src/components/header/index'

export default new Router({

    mode:'history',
    base:process.env.BASE_URL,
    routes:[
        {
            path:'/user',
            component: () => import( /* webpackChunkName: "layout" */ '@/src/layout/index'), //异步加载组件内容
            children:[
                {
                    path:'/user/login',
                    name:'login',
                    component: () => import( /* webpackChunkName: "user" */ '@/src/views/User/Login')
                }
            ]
        }
    ]
})
4、实现一个可动态改变的页面布局

(1)、依据布局引入各个组件

(2)、依据框架主题,传入变化的参数,设置不同的class样式,以及theme主题的选择

(3)、依据router的设置即可更换主题样式以及相应细节的修改

5、菜单与路由的结合

(1)、设置路由相关参数 如:title、menu、name、标志属性等

(2)、递归的方式获取路由list[]数据

export default {
    data() {
        const menuData = this.getMenuData(this.$router.options.routes)
        return {
            collapsed:false,
            menuData,
            selectedKeys: this.selectedKeysMap[this.$route.path],
            openKeys: this.collapsed?[]:this.openKeysMap[this.$route.path],
        }
    },
    watch:{
        '$route.path':function(val){
            this.selectedKeys = this.selectedKeysMap[val];
            this.openKeys = this.collapsed?[]:this.openKeysMap[val];
        }
    },
    methods: {
        getMenuData(routes = [], parentsKeys = [], selectedKey){
            const menuData = [];
            routes.forEach(item => {
                if(item.name && !item.hideInMenu) {
                    this.openKeysMap[item.path] = parentKeys;
                    this.selectedKeysMap[item.path] = [item.path || selectedKey];
                    const newItem = { ...item };
                    delete newItem.children;
                    if(item.children && !item.hideChildrenMenu) {
                        newItem.children = this.getMenuData(item.children,[...parentKeys,item.path]);
                    }else {
                        this.getMenuData(item.children,selectedKey? parentKeys:[...parentKeys,item.path],selectedKey || item.path);
                    }
                    menuData.push(newItem);
                }else if (
                    !item.hideInMenu &&
                    !item.hideChildrenInMenu &&
                    item.children
                ){
                    menuData.push(...this.getMenuData(item.children))
                }
            });
            return menuData;
        }
    }
}

(3)、路由跳转与菜单组件点击事件相关联,从而使点击菜单,路由跟着变换

添加点击事件:

@click="() => $router.push({path :item.path})"

或者:

@click="() => parent.$router.push({path :item.path})"

不同的框架获取路由的方式不同,点击事件绑定也不同,可根据数据接口获取路由数据,然后依据框架需要,处理菜单点击事件与路由跳转的关系
6、路由管理用户权限

(1)、建立验证权限的js文件,依据需求写验证规则

utils ---> auth.js

//获取权限--依据后台数据返回确定相应权限
export function getCurrentAuthority(){
    return ["admin"]
}

//权限验证--检查当前用户是否拥有此页面的查看权限
export function check(authority){
    const current = getCurrentAuthority()
    return current.some(item => authority.includes(item));
}

//判断是否登录
export function isLogin(){
    const current = getCurrentAuthority();
    return current && current[0] != "guest"
}

(2)、通过设置路由参数,进而判断权限

//在路由中设置meta参数

{
    path:'/',
    name:'index',
    meta:{
        title:'首页'
        authority:['admin','user']
    }
    component:Home,
},
{
    path:'/form',
    name:'form',
    meta:{
        title:'表单'
        authority:['user']
    }
    component:Home,
}
。。。

router.beforeEach((to,from,next)) => {
    if(to.path !== from.path){
        NProgress.start();
    }
    
    // 获取当前路由最近的用户权限,并记录下来  findLast是一个依赖,下载即可
    const record = findLast(to.matched,record => record.meta.authority);
    
    //对当前路由用户权限进行验证,若有相应权限,及展示列表项,若没有则登录
    if(record && !check(record.meta.authority)) {
        if(!isLogin() && to.path !== "/user/login"){
            next({
            
                path:'/user/login'
            })
        }else if( to.path != '/403'){
            notification.error({
            
                message:'403',
                description:"请联系管理员"
            });
            next({
                path:'/403'
            })
        }
        NProgress.done()
    }
    next()
}
7、如何在组件中使用EChart、Antv等图表插件

(1)、下载echart依赖

npm install echart -S -D
yarn add echart

(2)、设置图表展示样式响应式

npm install resize-detector

在组件中引用

import { addListener, removeListener } from 'resize-detector'

使用:
monted(){
    this.chart = echarts.init(this.$refs.chartDom,this.resize)
    
    //在图表生成时依据屏幕自适应宽度、高度
    addListener(this.$refs.chartDom,this.resize)
},
//在组件销毁时,移除图表自适应事件,并将图表数据销毁
beforeDestory(){
    removeListener(this.$refs.chartDom,this.resize)
    this.chart.dispose()  //移除图表Dom
    this.chart = null
},
methods:{
    //图表自适应事件
    resize(){
        this.chart.resize()
    }
}

(3)、设置图表自适应防抖事件

下载debounce

npm install debounce

引入:

import debounce from 'lodash/debounce'

使用:

created(){
    this.resize = debounce(this.resize,300);
}

(4)、实时更改传入组件的图表值

方法一:watch深度监听图表options

//组件中
watch:{
    options:{
        handler(val){
            this.chart.setOptions(val);
        },
        deep:true
    }
}

//使用组件的.vue中
mounted(){
    this.interval = setInterval(() => {
        this.chartOption.series[0].data = this.chartOption.series[0].data.map(() => random(100))
    }, 3000);
},

beforeDestory(){
    clearInterval(this.interval);
}

方法二:直接监听option,更改之后直接付新值

//组件中
watch:{
    option(val){
        this.chart.setOptions(val);
    }
}

//使用组件的.vue中
mounted(){
    this.interval = setInterval(() => {
        this.chartOption.series[0].data = this.chartOption.series[0].data.map(() => random(100))
        this.chartOption = { ...this.chartOption }
    }, 3000);
}
8、高效使用 Mock 数据进行开发

(1)、下载axios,并书写接口

npm install axios

import axios from 'axios'

getChartData(){
    axios.get('/api/dashboard/chart',{ params:{ ID: 12345 }}).then((res) => {
        this.chartOption = { ... } 
    })
}

(2)、在mock文件中设置数据返回规则

dashboard_chart.js文件中

function chart(method){
    let res = null;
    switch(method){
        case 'GET':
            res = [100, 20, 60, 120, 80, 70 ];
            break;
        default:
            res = null
    }
    return res
}

//模块化输出:
module.export = chart 

(3)、在vue.config.js文件中,修改接口处理方式,接口反向代理模式,对接口进行统一处理

module.export = {
    devServer:{
        proxy:{
            "/api":{
                target:"http://localhost:3000",
                bypass:function(req,res){
                    if(req.headers.accept.indexOf("html") !== -1){
                        console.log("...")
                        return '.index.html';
                    }else{
                        const name = req.path.split("/api/")[1].split('/').join('_');
                        const mock = require(`./mock/${name}`);
                        const result = mock(req.method);
                        //赋值前清一下之前的数据缓存
                        delete require.cache[require.resolve(`./mock/${name}`)]
                        return res.send(result);
                    }
                }
            }
        }
    }
}
9、与服务端进行交互

(1)、后台服务端接口与前端创建的mock环境进行切换,方便随时切换环境

在 package.json文件中,修改项目启动方式

scripts:{
    'serve':'vue-cli-service serve',
    'serve:no-mock':'corss-env MOCK=none vue-cli-service serve',
    'build':'vue-cli-service build',
    'lint':'vue-cli-service lint',
    'test:unit':'vue-cli-service test:unit'
}

修改一下vue.config.js 文件

module.export = {
    devServer:{
        proxy:{
            "/api":{
                target:"http://localhost:3000",
                bypass:function(req,res){
                    if(req.headers.accept.indexOf("html") !== -1){
                        console.log("...")
                        return '.index.html';
                    
                    //判断一下,项目运行环境不是MOCK的时候就切换到MOGK数据模式
                    }else if( process.env.MOCK !== 'none'){
                        const name = req.path.split("/api/")[1].split('/').join('_');
                        const mock = require(`./mock/${name}`);
                        const result = mock(req.method);
                        //赋值前清一下之前的数据缓存
                        delete require.cache[require.resolve(`./mock/${name}`)]
                        return res.send(result);
                    }
                }
            }
        }
    }
}

(2)、在utils文件中建立request.js 文件,对请求接口axios进行header、token、method等参数的封装,以及对返回数据的封装处理

10、管理系统中使用图标的方式

(1)、各个小图标拼接在一张图片上

(2)、使用字体图标

(3)、SVG形式使用图标

方法一:使用iconfont网站中的svg图标

const MyIcon = Icon.createFromIconfontCN({
    scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', // generated by iconfont.cn
});

Vue.component('MyIcon',MyIcon)

//使用:

<my-icon type="icon-example" />

方法二:直接引入SVG形式的图片

将SVG图片放入项目中存放,一般放在assets文件夹下面,vue中会将svg图片解析成url形式的字符串
 
//引入图片 
import logoSvg from '@/assets/logoSvg.svg' 
 
//通过img标签引入 
<img :src="logoSvg" alt >

方法三:配置 vue-svg-loader 组件

安装 vue-svg-loader 依赖

添加vue-cli配置,在vue.config.js中设置:

// vue.config.js
module.exports = {
  chainWebpack: config => {
    const svgRule = config.module.rule('svg')

    // 清除已有的所有 loader。
    // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
    svgRule.uses.clear()

    // 添加要替换的 loader
    svgRule
      .use('vue-svg-loader')
        .loader('vue-svg-loader')
  }
}

使用:

import logoSvg from '@/assets/logoSvg.svg' 

components:{
    logoSvg
}

<logoSvg />
11、将全部this.$route的参数传过去,然后传入其他参数
this.$router.push({query: {...this.$route.query, local:key} })

vue i18n 是vue.js 的国际化插件库,可以实现组件语言切换
12、高效构建打包发布
A:图标按需加载是将所用的图标先下载在本地,然后采用别名,将图标请求直接请求本地图标。

vue.config.js文件中:

configuerWebpack:{
    plugins:[themePlugin],
    resolve:{
        alise:{
            "@ant-design/icons/lib/dist$":path.resolve(_dirname,"./src/icons")
        }
    }
}

B:moment配置优化:将moment引入的包全部隐藏掉

configuerWebpack:{
    plugins:[themePlugin, new webpack.IgnorePlugin(/^\.\/locale$/,/moment$s/)],
    resolve:{
        alise:{
            "@ant-design/icons/lib/dist$":path.resolve(_dirname,"./src/icons")
        }
    }
}

C:此时moment语言包需要手动的引入进来

import "moment/locale/zh-cn"

D:echarts按需引入:如只引进柱状图插件

import echarts from "echarts/lib/echarts";
import "echarts/lib/chart/bar";
import "echarts/lib/component/title";
13、构建可交互的组件文档

1、vue-highlightjs 使代码高亮显示

//下载依赖

npm install --save vue-highlightjs


//main.js中使用:

import Vue from 'vue'

import VueHighlightJS from 'vue-highlightjs'

vue.use(VueHighlightJS)


//页面中使用:

//先引入代码,利用raw-loader将代码处理成字符串加载出来
import chartCode from "!!raw-loder!../../components/Chart"

//在组建中将代码字符串加载出来
<pre v-highlightjs="chartCode"><code class="html"></code></pre>

//引入highlightjs样式组件 main.js中引入:
import "highlight.js/style/github.css"
14、将组件发布到npm上

1、需要一个npm账号

2、组件本地要有package.json文件 —最小要有name、version两个字段

3、在npm或者公司私有的开发源发布即可 推荐 nrm 来管理开发源

举报

相关推荐

0 条评论