面试

88 阅读8分钟

怎么判断登陆的人能不能访问她做的页面给你一个项目,中间怎么组建怎么插件,怎么部署

给你一个项目,中间怎么组建怎么插件,怎么部署

  1. 创建一个新的axios实例 2.请求拦截器,如果有token进行头部携带
  2. 响应拦截器:1. 剥离无效数据 2. 处理token失效
  3. 导出一个函数,调用当前的axsio实例发请求,返回值promise

在每一个路由的 meta 属性里,将能访问该路由的角色添加到 roles 里。用户每次登陆后,将用户的角色返回。然后在访问页面时,把路由的 meta 属性和用户的角色进行对比,如果用户的角色在路由的 roles 里,那就是能访问,如果不在就拒绝访问。

routes: [
    {
        path: '/login',
        name: 'login',
        meta: {
            roles: ['admin', 'user']
        },
        component: () => import('../components/Login.vue')
    },
    {
        path: 'home',
        name: 'home',
        meta: {
            roles: ['admin']
        },
        component: () => import('../views/Home.vue')
    },]

代码部署到本地,分哪几个阶段干什么…

  • 主机名(ip地址,例如:108.159.12.67
  • 用户名(一般是 root )
  • 密码 (登入服务器的密码)
  • 端口 (一般是 22 )

在package.json中script加上 --host 0.0.0.0

let hostname = window.location.hostname; //主机 let baseurl='http://'+hostname+':8080/'

修改打包命令默认启动ip

  • 找到:package.json

把"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",

修改为:

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0" 2

  • 修改localhost

找到config>>index.js

把host: 'localhost' 修改为:

Host: '0.0.0.0'3

  • 关闭防火墙

打包的工具NPM

npm即node的包管理器,是Node.js默人的、以JavaScript编写的软件包管理系统

查看全局安装了那些包
$ npm list -g
1
查看版本
$ npm jquery -v
1
指定下载包的版本(在包名后添加@符号后跟版本号)
$ npm i jquery@1.1.2

vuex属性 微任务,宏任务执行时机 事件循环

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。 (1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 (2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。 主要包括以下几个模块:

State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。 Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。 Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。 Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。 Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中

作者:我是你的超级英雄 链接:juejin.cn/post/684490… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

vue.config配置

vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。

module.exports = {
    // 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath
    // baseUrl: process.env.NODE_ENV === 'production' ? './' : '/' 
    publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './',
    // 输出文件目录:在npm run build时,生成文件的目录名称 
    outputDir: 'dist',
    // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 
    assetsDir: "assets",
    // 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 
    productionSourceMap: false,
    // 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变)
    filenameHashing: false,
    // 代码保存时进行eslint检测
    lintOnSave: false,
    // webpack-dev-server 相关配置
    devServer: {
        // 自动打开浏览器
        open: true,
        host: 'localhost',
        // 端口
        port: 9930,
        // https
        https: false,
        // 热更新
        hotOnly: false,
        // 使用代理
        proxy: {
            '/api': {
                // 目标代理服务器地址
                target: 'http://47.100.47.3/',
                // 开启代理,本地创建一个虚拟服务器 允许跨域
                changeOrigin: true, 
            },
        },
    },
}

elementUI按需导入

如果你只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容(vue项目中):

import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';

Vue.use(Button)
Vue.use(Select)

/* 或写为
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
*/
特点:

垂直居中方法

 display: flex;
            justify-content: center;
            align-items: center;
 display: table-cell;
            vertical-align: middle;
            text-align: center;

父子、兄弟、爷孙组件通信

1)props / emit适用父子组件通信这种方法是Vue组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。(2refemit 适用 父子组件通信 这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。 (2)ref 与 parent / $children 适用 父子组件通信

ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例 parent/parent / children:访问父 / 子实例

(3)EventBus (emit/emit / on) 适用于 父子、隔代、兄弟组件通信 这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。 (4)attrs/attrs/listeners 适用于 隔代组件通信

attrs:包含了父作用域中不被prop所识别(且获取)的特性绑定(classstyle除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(classstyle除外),并且可以通过vbind="attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。 listeners:包含了父作用域中的(不含.native修饰器的)von事件监听器。它可以通过von="listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="listeners" 传入内部组件

(5)provide / inject 适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。 (6)Vuex 适用于 父子、隔代、兄弟组件通信 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

作者:我是你的超级英雄 链接:juejin.cn/post/684490… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

webpack配置

chunk:指代码块,一个 chunk 可能由多个模块组合而成,也用于代码合并与分割。

bundle:资源经过Webpack 流程解析编译后最终结输出的成果文件。

entry:顾名思义,就是入口起点,用来告诉webpack用哪个文件作为构建依赖图的起点。webpack会根据entry递归的去寻找依赖,/+++每个依赖都将被它处理,最后输出到打包成果中。

output:output配置描述了webpack打包的输出配置,包含输出文件的命名、位置等信息。

loader:默认情况下,webpack仅支持.js .json文件,通过loader,可以让它解析其他类型的文件,充当翻译官的角色。理论上只要有相应的loader,就可以处理任何类型的文件。

plugin:loader主要的职责是让webpack认识更多的文件类型,而plugin的职责则是让其可以控制构建流程,从而执行一些特殊的任务。插件的功能非常强大,可以完成各种各样的任务。

webpack的功能补充

mode:4.0开始,webpack支持零配置,旨在为开发人员减少上手难度,同时加入了mode的概念,用于指定打包的目标环境,以便在打包的过程中启用webpack针对不同的环境下内置的优化。。


const path = require("path");
module.exports = {
  // 必填  webpack执行构建入口
  entry: "./src/index.js",
  output: {
    //  将所有依赖的模块合并输出到main.js
    filename: "main.js",
    //  输出文件的存放路径,必须是绝对路径
    path: path.resolve(__dirname, "./dist")
  }

keepaliy缓存

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

一般结合路由和动态组件一起使用,用于缓存组件; 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高; 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

作者:我是你的超级英雄 链接:juejin.cn/post/684490… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

动态路由配置

所有的静态路由和动态路由,都写完了,接下来就是关键部分(将后台返回的路由json拼接到route内),由于我们是在login页面点击登陆后,进行的跳转,所以,把代码写到路由钩子内(Routers.beforeach函数)

Routers.beforeEach((to,from,next) => {
    if(to.path != '/' && !store.state.isLogin) {
        //跳转的不是首页 同时 用户还未登陆
        //这个判断,我们就可以基本判定用户是在做登陆时候的跳转
        //↓拿到登陆时,接口返回的路由数组(vuex内),大致是这样的
        let resRouterArr = [            {                routeName: '人员管理',                children: [                    {                        routeName: '销售管理',                        ...                    },                    {                        routeName: '内勤管理',                        ...                    }                ]
            }
        ]
        let routerArr = []
        resRouterArr.forEach(item => {
            allRouters.forEach(all => {
                if(item.routeName == all.routeName) {
                    //拿到本地路由对象
                    let obj = JSON.parse(JSON.stringify(all))
                    let childrenRouter = []
                    if(item.children && item.children.length > 0) {
                        item.children.forEach(childItem => {
                            all.children.forEach(allItem => {
                                if(childItem.routeName == allItem.routerName) {
                                    childrenRouter.push(allItem)
                                }
                            })
                        })
                        obj.children = childrenRouter
                    }
                    routerArr.push(obj)
                }
            })
        })
        Routers.addroutes(routerArr)//addroutes为添加路由数组的方法
        store.commit('domRouteTree',rousterArr)//存储进vuex,之后页面左右路由列表渲染使用
        next({...to,replace:true})//进行路由跳转
    } else {
        next()
    }
})
    

页面优化方法

(1)代码层面的优化

  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分使用场景
  • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if-
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入 = 优化无限列表性能
  • 服务端渲染 SSR or 预渲染

(2)Webpack 层面的优化

  • Webpack 对图片进行压缩
  • 减少 ES6 转为 ES5 的冗余代码
  • 提取公共代码
  • 模板预编译
  • 提取组件的 CSS
  • 优化 SourceMap
  • 构建结果输出分析
  • Vue 项目的编译优化

(3)基础的 Web 技术的优化

  • 开启 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈

请求组件封装

apply call bind区别

一、call,apply,bind的相同点:

  • 都是改变this指向的;
  • 第一个参数都是this要指向的对象;
  • 都可以利用后续参数传参;

二、call,apply,bind的区别:

  • call和bind的参数是依次传参,一一对应的;
  • 但apply只有两个参数,第二个参数为数组;
  • call和apply都是对函数进行直接调用,而bind方法返回的仍是一个函数;

节流防抖实现

高频率触发的事件,在指定的单位时间内,只响应第一次(前面触发的执行前,忽略后面的事件)

二、防抖 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间在触发,则重新计算时间(后面触发的事件执行,替代了前面的事件)

防抖(debounce)

  • .search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
  • .window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次。

节流(throttle)

  • .鼠标不断点击触发,mousedown(单位时间内只触发一次)。
  • .监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断。