安装 axios🌟🌟
- 安装依赖》运行依赖》axios
- 使用 axios 发送请求
- 利用 Vue.prorotype 挂载到原型上
vue 动画🌟🌟
利用类名添加动画
在进入/离开的过渡中,会有 6 个 class 切换。
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to
: 2.1.8 版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。v-leave
: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
: 2.1.8 版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
- 首先给需要添加动画的元素用 transition 包裹起来
- 利用类名实现动画
.v-enter, .v-leave-to { transform: translate(200px, 0); } .v-enter-active, .v-leave-active { transition: transform 1s; } .v-enter-to, .v-leave { transform: translate(0, 0); }
自定义动画类名
<transition name="box2"> <div class="box" v-show="flag"></div> </transition>
.box2-enter, .box2-leave-to { opacity: 0; } .box2-enter-active, .box2-leave-active { transition: opacity 1s; } .box2-enter-to, .box2-leave { opacity: 1; }
结合 css 动画库设置动画🌟🌟
- 引入 css 动画库
- 通过 enter-active-class、leave-active-class 设置动画
<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" > <div class="box" v-show="flag"></div> </transition>
vuex 的缺陷🌟🌟🌟
vuex 的数据属于应用级别的数据,应用刷新,数据会重置 (具有响应式, 不能持久存储)
结合本地存储来使用
单纯的使用本地: 本地的数据(持久存储,不具有响应式)
vue 单页面应用的优缺点🌟🌟🌟🌟
缺点:
- 不利于 seo
- 兼容到 ie9
- 初次加载耗时相对增多
优点
- 用户体验好,不用重新刷新整个页面
- 前后端分离
- mvvm 设计模式
- 减轻服务期压力,只需要服务器提供数据
加深面试题
关于项目打包你都做了什么? 你的项目优化具体做了哪些? 你的项目如何打包的?🌟🌟🌟🌟🌟
- 移除 console,借助 babel 插件 babel-plugin-transform-remove-console
- 判断环境,只在发布阶段使用上面的插件, 通过 process.env.NODE_ENV ‘production’ || “development”
- 因为开发阶段和发布阶段入口代码有区别,通过 chainWebpack 配置自定义的打包入口,
// 配置自定义入口文件 chainWebpack: config => { // when: 相当于if 第一个参数:(条件) 第二个参数(满足条件执行的回调函数) if(条件) { 满足条件执行的逻辑 } // 开发期间 --- main-dev.js config.when(process.env.NODE_ENV === 'development', config => { config .entry('app') .clear() .add('./src/main-dev.js') }) // 发布阶段 --- main-prod.js config.when(process.env.NODE_ENV === 'production', config => { config .entry('app') .clear() .add('./src/main-prod.js') }) }
- 发布阶段为了减小打包体积, 忽略 js 打包,配置 externals,关于 css 样式,在发布的入口文件中注释掉即可, 加载 cdn 资源文件,加载 cdn 资源文件的优势,减小自己服务器的压力,同时 cdn 资源会就近原则访问
- 只在发布阶段使用 cdn 资源,通过给 htmlwebpackPlugin 添加标识,标识为不同的值,此时就可以在 html 中判断 htmlwebpackPlugin 标识为开发阶段还是发布阶段从而按需加载 cdn 资源
- 路由懒加载,路由按需加载, 匹配到哪个路由规则,加载对应的资源文件
虚拟 dom🌟🌟🌟
本质上就是一个 JS 对象,用来描述你希望在屏幕上看到的内容
作用:描述了真实dom结构,核心属性
真实的dom节点有很多属性的,如果直接操作真实的dom,消耗性能
vue里面template写的结构转换render函数,render函数执行会返回虚拟dom结构 >> 渲染出真实dom
优势:
1、数据更新的时候,虚拟dom对比(旧的虚拟dom结构和新的虚拟dom结构进行对比),对比出差异以后,更新到真实的dom里面(最小化操作dom)
2、同级比较,如果标签名不一致或者key不一致直接替换,不会进行深层次对比
3、次序深度优先
跨平台
浏览器,小程序 , 支付宝小程序,抖音小程序,打包安卓,ios应用 ,electron桌面应用
vue/react >> 虚拟dom 渲染的时候根据不同的平台去进行渲染
渲染浏览器环境的方法
渲染小程序的方法
dom diff的性能好
跨平台
Diff 算法🌟🌟🌟🌟
虚拟 dom 高效更新执行过程
- 初次渲染时,会根据 model 数据创建一个虚拟 DOM 对象(树)
- 根据虚拟 DOM 生成真正的 DOM,渲染到页面
- 当数据变化后,会重新根据新的数据,创建新的虚拟 DOM 对象(树)
- 与上一次得到的虚拟 DOM 对象,使用 Diff 算法比对(找不同),得到需要更新的内容
- 最终,React 只将变化的内容更新(patch)到 DOM 中,重新渲染到页面
- 什么是虚拟 dom:用 js 对象来表示页面上 dom 元素的的样式体现
- 虚拟 dom 的作用:高效更新页面,还有就是让 react 脱离了浏览器的概念
- 怎么来高效更新页面的:就是在第一次渲染页面的时候生成一份初始的虚拟 dom 树,然后当数据改变之后,再生成一份虚拟 dom 树,然后根据新旧 dom 树进行对比,对比完成之后,把有区别的进行更新
- diff 算法的作用就是:新旧虚拟 dom 树在对比的时候就是通过 diff 算法来对比的
- diff 算法又是怎么去对比的:tree diff、component diff、element diff
面试语术:
你知道虚拟 dom 吗?简单又谈一下?
本质上就是一个 JS 对象,用来描述你希望在屏幕上看到的内容,虚拟 dom 可以实现高效更新,(后面如果自己能说一气说出来)
如何实现高效更新的?
利用新旧虚拟 dom 树进行对比,从而进行局部进行更新
如何进行新旧 dom 树进行对比?
利用 diff 算法,主要是 tree diff 树对比,component diff 组件对比,element diff 元素对比
加上一些其他话术
所以虚拟 dom 在前端中不管是 vue、react 等等都采用
axios 配置代理服务器🌟🌟🌟🌟
什么是跨域?
在浏览器里面域名、端口、ip 地址、协议,有任何一项不同,则跨域
A 网站:http://localhost:8080/#/
B 网站:http://localhost:3000/#/
处理跨域的方式?
JsonP(只能处理 get 请求)、cors(后端开启)、代理服务器
module.exports = { devServer: { host: 'localhost', port: 8080, proxy: { '/api': { target: 'http://localhost:3000', // 要跨域的域名 changeOrigin: true // 是否开启跨域 }, '/get': { target: 'http://localhost:3000', // 要跨域的域名 changeOrigin: true // 是否开启跨域 } } } }
小程序分包加载🌟🌟🌟
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
目前小程序分包大小有以下限制:
- 整个小程序所有分包大小不超过 12M
- 单个分包/主包大小不能超过 2M
对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。
代码演示,分包加载之前
pages: [ 'pages/tabs/home', 'pages/tabs/cates', 'pages/tabs/search', 'pages/tabs/cart', 'pages/tabs/my', 'pages/goods_list', 'pages/goods_detail/main', 'pages/order', 'pages/orderList' ]
抽离之后
pages: [ 'pages/tabs/home', 'pages/tabs/cates', 'pages/tabs/search', 'pages/tabs/cart', 'pages/tabs/my', 'pages/order', 'pages/orderList' ], subpackages: [ { name: 'goods', root: 'goods', pages: [ 'goods_list', 'goods_detail/main' ] } ]
图片或者图标等资源文件使用线上资源
v-if 和 v-for 避免结合使用🌟🌟🌟
因为 v-for 的优先级大于 v-if,所以会先根据所有数据生成结构,然后在根据,v-if 进行按需渲染
<div id="app"> <ul> <li v-for="item in arr" v-if="item%2===0">{{ item }}</li> </ul> </div> <script src="./vue.js"></script> <script> new Vue({ el: '#app', data: { arr: [1, 2, 3, 4] } }) </script>
我们可以采用计算属性来避免此问题,这样的话,先通过计算属性,计算出要渲染的数据,然后直接循环计算属性即可
<div id="app"> <ul> <li v-for="item in newArr">{{ item }}</li> </ul> </div> <script src="./vue.js"></script> <script> new Vue({ el: '#app', data: { arr: [1, 2, 3, 4] }, computed: { newArr() { return this.arr.filter(item => { return item % 2 === 0 }) } } }) </script>
vue 中 route 和 router 的区别🌟🌟🌟🌟
- route 是当前路由信息,可以获取到当前路由地址参数等等
- router 是全局路由(VueRouter)实例对象,可以通过 router 进行路由的跳转后退等等
如何封装一个插件🌟🌟
- 定义一个 button 组件,在 index.js 中引入并注册
- 在 components 中创建一个 index.js
import sgButton from './button.vue' function install (Vue) { Vue.component(sgButton.name, sgButton) } export default { install }
- 在 main.js 中导入该 js 文件,当调用 Vue.use 方法,会默认调用内部的 install 方法
面试题
你有封装过插件吗? Vue.use 的原理是什么?
当调用 Vue.use 方法,会默认调用内部的 install 方法,install 这个方法默认的第一个形参就是 Vue,这样的话我们就可以通过 Vue 注册一些全局组件,给 Vue 扩展一下方法。
vueI18n 的使用🌟🌟
vue 中实现语言切换的方式如何实现的
1.NPM 项目安装
cnpm i vue-i18n
2.使用方法
/* 国际化使用规则 */ import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) <!-- 需要国际化的数据定义在此处 --> const messages = { en: { message: { hello: 'world hello' } }, zh: { message: { hello: '世界' } } } <!-- 使用i18n --> const i18n = new VueI18n({ locale: 'zh', messages }) export default { data () { return { hello: this.$t('message.hello') } }, i18n }
3.页面数据使用
<div id="#app"> <p>{{ $t("message.hello") }}</p> </div>
4.案例练习
定义基本结构
<div id="app"> <button>切换语言</button> <ul> <li>首页</li> <li>新闻</li> <li>关于</li> <li>概况</li> </ul> </div> ul{ list-style: none; li{ width: 20%; height: 70px; line-height: 70px; background: green; color: #fff; float: left; margin-left: 2%; text-align: center; line-height: 70px; } }
定义语言包
zh.js
export default { nav: ['首页', '新闻', '概况', '关于'] }
en.js
export default { nav: ['home', 'news', 'gk', 'about'] }
在 main.js 中引入语言包
.import zh from './i18n/zh.js' import en from './i18n/en.js' Vue.use(VueI18n) const i18n = new VueI18n({ locale: 'en', messages: { zh, en } })
数据渲染和切换
<template> <div id="app"> <button @click="changeLang">切换语言</button> <ul> <li v-for="(item, index) in $t('nav')" :key="index"> {{ item }} </li> </ul> </div> </template> <script> export default { methods: { changeLang() { this.$i18n.locale = this.$i18n.locale === 'en' ? 'zh' : 'en' } } } </script>
keep-alive🌟🌟🌟🌟
- vue自带的组件 >> 主要功能是缓存组件 >> 提升性能
- 使用场景:可以少网络请求,如果当前组件数据量比较大,就可以节省网络请求 >> 提升用户体验
- 举例:如果详情页面之间进行切换,就可以使用
keep-alive
进行缓存组件,防止同样的数据重复请求
<keep-alive> <router-view /> </keep-alive>
一、Keep-alive 是什么
keep-alive
是
vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染
DOM
keep-alive
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
keep-alive
可以设置以下props
属性:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存max
- 数字。最多可以缓存多少组件实例
关于keep-alive
的基本用法:
<keep-alive> <component :is="view"></component> </keep-alive>
使用includes
和exclude
:
<keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <!-- 正则表达式 (使用 `v-bind`) --> <keep-alive :include="/a|b/"> <component :is="view"></component> </keep-alive> <!-- 数组 (使用 `v-bind`) --> <keep-alive :include="['a', 'b']"> <component :is="view"></component> </keep-alive>
匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值),匿名组件不能被匹配
设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated与deactivated):
- 首次进入组件时:beforeRouteEnter > beforeCreate > created> mounted > activated > … … > beforeRouteLeave > deactivated
- 再次进入组件时:beforeRouteEnter >activated > … … > beforeRouteLeave > deactivated
二、使用场景
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive
举个栗子:
当我们从首页
–>列表页
–>商详页
–>再返回
,这时候列表页应该是需要keep-alive
从首页
–>列表页
–>商详页
–>返回到列表页(需要缓存)
–>返回到首页(需要缓存)
–>再次进入列表页(不需要缓存)
,这时候可以按需来控制页面的keep-alive
vue-router 中 hash 和 history 的区别
- history 没有#/,会比 hash 好看
- history 模式是采用的 h5
history.pushState
API 来完成 URL 跳转而无须重新加载页面 - hash 是利用 location.hash 进行跳转的
- hash 是不需要后台配置支持的
- history 不过这种模式要玩好,还需要后台配置支持
this.$nextTick()的作用
这个函数是可以等 dom 重新更新完成会调用
数据渲染完成,页面完成更新即调用 this.$nextTik
当修改了数据,dom 是异步同步的,所以,如果更改了数据,在修改数据下面重新操作 dom 会出问题,需要保证 dom 也更新完成才能操作。