1. keep-alive 组件的作用
为什么使用 keep-alive?
在 vue 中, 我们使用 component 内置组件或者 vue-router 切换视图的时候, 由于 Vue 会主动卸载不使用的组件, 所以我们不能保存组件之前的状态, 而我们经常能遇到需要保存之前状态的需求, 例如搜索页 (保存搜索记录), 列表页(保存之前的浏览记录) 等等
keep-alive 的作用?
keep-alive 是一个 Vue 的内置组件, 它能将不活动的组件保存下来, 而不是直接销毁, 当我们再次访问这个组件的时候, 会先从 keep-alive 中存储的组件中寻找, 如果有缓存的话, 直接渲染之前缓存的, 如果没有的话, 再加载对应的组件.
作为抽象组件, keep-alive 是不会直接渲染在 DOM 中的
keep-alive 的属性?
keep-alive 提供了三个可选属性
include - 字符串或数组或正则表达式. 只有名称匹配的组件会被缓存.
- //** 字符串 ** 只缓存 a 组件
- <keep-alive include="a">
- <component :is="componentName"></component>
- </keep-alive>
- //** 字符串 ** 只缓存 a 组件和 b 组件
- <keep-alive include="a,b">
- <component :is="componentName"></component>
- </keep-alive>
- //** 正则表达式, 需要使用 v-bind ** 只缓存 a 组件和 b 组件
- <keep-alive :include="/a|b/">
- <component :is="componentName"></component>
- </keep-alive>
- //** 数组, 需要使用 v-bind ** 只缓存 a 组件和 b 组件
- <keep-alive :include="[a,b]">
- <component :is="componentName"></component>
- </keep-alive>
exclude - 字符串或数组或正则表达式. 名称匹配的组件不会被缓存.
- //** 字符串 ** 不缓存 a 组件
- <keep-alive exclude="a">
- <component :is="componentName"></component>
- </keep-alive>
- //** 字符串 ** 不缓存 a 组件和 b 组件
- <keep-alive exclude="a,b">
- <component :is="componentName"></component>
- </keep-alive>
- //** 正则表达式, 需要使用 v-bind ** 不缓存 a 组件和 b 组件
- <keep-alive :exclude="/a|b/">
- <component :is="componentName"></component>
- </keep-alive>
- //** 数组, 需要使用 v-bind ** 不缓存 a 组件和 b 组件
- <keep-alive :exclude="[a,b]">
- <component :is="componentName"></component>
- </keep-alive>
max - 数字类型. 表示最多可以缓存多少组件实例.
- <keep-alive :max="10"> <!-- 表示最多缓存十个组件实例 -->
- <component :is="view"></component>
- </keep-alive>
对于 keep-alive 需要知道的事情?
keep-alive 提供了两个生命钩子, 分别是 activated 与 deactivated.
因为 keep-alive 会将组件保存在内存中, 并不会销毁以及重新创建, 所以不会重新调用组件的 created 等方法, 需要用 activated 与 deactivated 这两个生命钩子来得知当前组件是否处于活动状态.
- <script>
- export default {
- name: 'componentA',
- activated() {
- console.log('组件激活了')
- }
- deactivated() {
- console.log('组件被缓存了')
- }
- }
- </script>
2. 单页面应用和多页面应用区别及优缺点
单页面应用(SPA), 其实就是指只有一个主页面的应用, 类似于前端现在的三大框架, React,Vue,Angular 浏览器一开始要加载所有必须的 html, JS, CSS. 所有的页面内容都包含在这个所谓的主页面中.
单页应用的原理是: 利用 JS 感知到 url 的变化, 通过这一点, 可以用 JS 动态的将当前的页面内容清除掉, 然后将下一个页面的内容挂载到当前的页面上. 页面每次切换跳转时, 并不需要做 HTML 文件的请求, 这样就节约了很多 http 发送时延, 我们在切换页面的时候速度很快.
单页面应用的优缺点:
优点
用户体验好, 快, 内容的改变不需要重新加载整个页面, 基于这一点 spa 对服务器压力较小
前后端分离
页面效果会比较炫酷(比如切换页面内容时的专场动画)
缺点
不利于 seo (搜索引擎优化)
导航不可用, 如果一定要导航需要自行实现前进, 后退.(由于是单页面不能用浏览器的前进后退功能, 所以需要自己建立堆栈管理)
初次加载时耗时多
页面复杂度提高很多
多页面(MPA), 就是指一个应用中有多个页面, 页面跳转时是整页刷新, 每次都请求一个新的页面,
优点
首屏时间快, seo 效果好
缺点
页面切换慢, 每次切换页面都需要选择性的重新加载公共资源
单页面应用与多页面应用的区别
图片来源 掘金: 前端: 你要懂的单页面应用和多页面应用
3. 什么是计算属性? 什么情况使用?
首先看一下什么是计算属性?
computed 是 Vue 的计算属性
为什么会有计算属性?
我们都知道的是, 在 Vue 的模板指令中我们可以书写一些简单的计算, 但是, 如果我们在模板指令中书写太多的逻辑运算的话, 会使得代码难以维护, 例如
<div>{{ count * price* discount + deliver }}</div>
我们不需要关注这个运算的结果是什么, 想象一下, 当你的项目中在模板指令存在这样的运算的时候, 你的代码将变得难以解读
什么情况下使用计算属性?
当我们需要一个值或者一个数据, 而这个数据需要通过一些逻辑运算才能得到的时候, 我们更希望将它放在计算属性内, 这样的话我们可以将整个项目对于数据的复杂运算逻辑全部集中管理在计算属性内
计算属性如何使用?
在一个计算属性里可以完成各种复杂的逻辑, 包括运算, 函数调用等, 只要最终返回一个结果就可以. 计算属性可以依赖多个 Vue 实例的数据, 还可以依赖其他计算属性; 而且计算属性不仅可以依赖当前 Vue 实例的数据, 还可以依赖其他实例的数据
只要其中任一数据变化, 计算属性就会重新执行, 视图也会更新.
- // template
- <div>{{totalPrice}}</div>
- // script
- computed: {
- totalPrice() {
- return this.count * this.price* this.discount + this.deliver;
- }
- }
这样我们就实现了一个最基础的计算属性
而计算属性还有一些稍微高级的用法
- // template
- <div>{{totalPrice}}</div>
- // script
- computed: {
- totalPrice: {
- get() {
- return this.count * this.price* this.discount + this.deliver;
- }
- set(newValue) {
- this.count = (newValue - this.deliver) / this.discount / this.price
- }
- }
- }
每一个计算属性都包含一个 getter 和一个 setter , 我们上面的示例中, 利用 getter 函数返回了计算属性的值, 并且提供一个 setter 函数, 当手动修改计算属性的值就像修改一个普通数据那样时, 就会触发 setter 函数, 执行一些自定义的操作.
可以看到的是, 计算属性可以是一个函数, 而我们在 Vue 中, methods 也是一个函数, 那我们同样可以通过 methods 中的方法来实现计算属性, 但是它们之间肯定是有区别的, 接着看一下它们之间的区别
4. computed,methods 的区别
computed 计算属性与 methods 方法的区别
computed 计算属性是基于内部的响应式依赖来进行计算并缓存的, 所谓的响应式依赖就是被我们的 Vue 实例所监听的数据
computed 计算属性是拥有缓存的, 我们每次访问同一个计算属性, 只要内部依赖没有发生改变, 它都不会重新计算
methods 方法是调用函数, 我们多次使用就等于多次调用了这个函数, 函数是没有缓存的, 所以每次都重新计算了, 当我们的内部依赖发生改变的时候, 都会重新 render 页面, 此时页面上所有调用了这个函数的地方都会再次重新调用这个函数
这也是我们为什么要使用计算属性, 而不是使用 methods 来计算一个数据.
5. 什么是自定义指令, 有哪些钩子函数及自定义指令的使用场景
自定义指令是什么? 以及自定义指令的使用场景
在 Vue 中, 有很多内置指令, 但是这些指令只能满足我们最基础的使用, 当我们在实际项目中遇到了必须要对 DOM 进行操作的逻辑时, 我们就用到了自定义指令
自定义指令的钩子函数 (这里我们可以直接看官网的介绍)
bind: 只调用一次, 指令第一次绑定到元素时调用. 在这里可以进行一次性的初始化设置.
inserted: 被绑定元素插入父节点时调用 (仅保证父节点存在, 但不一定已被插入文档中).
update: 所在组件的 VNode 更新时调用, 但是可能发生在其子 VNode 更新之前. 指令的值可能发生了改变, 也可能没有. 但是你可以通过比较更新前后的值来忽略不必要的模板更新.
componentUpdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用.
unbind: 只调用一次, 指令与元素解绑时调用.
钩子函数的参数
el - 绑定指令的 DOM 元素, 可以用来直接操作 DOM 元素
binding - 绑定指令时得到的值, 修饰符, 参数等
VNode - Vue 生成的虚拟 DOM 节点
oldVNode - 修改之前的 VNode, 只能在 update 函数和 componentUpdated 中调用
自定义指令的使用方法
- Vue.directive('drag', {
- bind(el,binding,VNode) {
- console.log('指令绑定成功')
- }
- inserted(el,binding,VNode) {
- console.log('当前 DOM 节点已经插入到父节点')
- }
- upate(el,binding,VNode,oldVNode) {
- console.log('当前 VNode 发生更新')
- }
- componentUpated(el,binding,VNode,oldVNode) {
- console.log('当前 VNode 更新成功')
- }
- unbind(el,binding,VNode) {
- console.log('指令与当前元素解绑')
- }
- })
- <div v-drag > 绑定指令的 div</div>
6. 父组件获取异步动态数据传递给子组件, 报错如何解决?
这个问题一般出现在对象, 或者我们直接调用数组指定下标的内容时会出现, 因为数组的话, 一般我们都是执行列表渲染, 数组内没有数据是不会执行遍历的, 而对象不一样, 如果没有对应的属性, 还是会调用, 只是返回 undefined, 而我们再调用 undefined 上的属性时, 就会出现报错
在父组件给子组件传值的时候, 给子组件加一个判断, 如果数据没有请求到就不渲染当前组件
- <div v-if="list.length>0">
- <child-compnent></child-component>
- </div>
- data() {
- return {
- list: []
- }
- }
- // 执行异步请求数据的方法和生命周期钩子等等
- methods: {
- getData() {
- // .....
- }
- }
7. vue-router 参数传递方法详述及区别
首先在 Vue 中 router 路由跳转分为两种
router.push(路由信息)
- 编程式导航
<router-link to="路由信息"></router-link>
- 声明式导航
这两种跳转方式传递参数是没有太大的区别的
vue-router 传参有两种方式, query 和 params
query 传参
<router-link to="/?tab=all">query 传参</router-link> this.$router.push('/?tab=all') <router-link :to="{ path:'/', query: {tab:'all'}}">query 传参</router-link> this.$router.push({ path: '/', query: {tab: 'all' }})
params 传参
<router-link to="/detail/1">query 传参</router-link> this.$router.push('/detail/1') <router-link :to="{ path:'/', params: { id: 1 } }">query 传参</router-link> this.$router.push({ path: '/', params: { id: 1 } })
query 和 params 传参的区别
params 是路由的一部分, 必须要在路由后面添加参数名. query 是拼接在 url 后面的参数, 没有也没关系.
params 一旦设置在路由, params 就是路由的一部分, 如果这个路由有 params 传参, 但是在跳转的时候没有传这个参数, 会导致跳转失败或者页面会没有内容.
query 会直接显示在 ? 后边 url?tab=all 而 params 是显示在路由的子路由上 url/name
使用方式不同, query 使用 this.$route.query 获取, params 使用 this.$route.params 获取
使用场景不同, query 一般用来做搜索或者列表页, 而 params 一般用来做详情页
结言
感谢您的查阅, 代码冗余或者有错误的地方望不吝赐教; 菜鸟一枚, 请多关照
来源: http://www.jianshu.com/p/b125644cb14d