前端八股-vue2.0

vue2生命周期

beforeCreate(){}#初始化之后、
created(){}#实例创建完成后被立即调用

beforeMount(){}#在挂载开始之前被调用
mounted(){}#被挂载后调用

beforeUpdate#数据更新时调用
updated(){}#组件 DOM 已经更新

beforeDestroy(){}#实例销毁之前调用
destroyed(){}#实例销毁后调用

activated(){}#被keep-alive 缓存的组件激活时调用
deactivated(){}#被keep-alive 缓存的组件停用时调用

errorCaptured(){}#捕获一个来自子孙组件的错误时被调用

补充:不要在updated中修改data数据,很容易造成死循环

#vue2 data设计原理

  • 原理:闭包设计:闭包可以保证每个组件有自己的私有作用域,而data是对象存在有干扰

  • 作用(data为什么是一个函数):保证组件的独立性,有私有作用域

  • 原因:如果data是对象的话,多个vue实例对应多个data,data是对象都会引用同一个内存地址;区分不同实例的data,只能是函数通过闭包的形式,实现data私有作用域

#vue2响应式原理

数据劫持+**发布订阅模式,**通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调

  • 原理:发布订阅模式 + 数据劫持
// 发布订阅
let Dep = {
  container: {},//容器
  // 添加订阅
  listen: function (key, fn) {
    if (!this.container[key]) {//如果没有容器为空,就给它设置默认值
      this.container[key] = [];
    }
    this.container[key].push(fn)
  },
  // 发布订阅
  trigger: function () {
    let key = Array.prototype.shift.call(arguments),//类数组转换(arguments本身就是类数组)
      fns = this.container[key];//获取打的容器内容
    if (!fns || fns.length === 0) {   //容器或容器内容为空直接结束
      return false
    }
    for (let i = 0, fn; fn = fns[i++];) {//通过遍历吧每个信息单独存起来
      fn.apply(this, arguments)//改变this的指向
    }
  }
}

// 数据劫持
let dataHijack = function ({ data, tag, tagkey, selector }) {//data数据,tag目标值,tagkey目标的键值,selector选择的元素
  let value = '',
    el = document.querySelector(selector);
  //双向数据绑定
  Object.defineProperty(data, tagkey, {
    get: function () {
      console.log('取值')
      return value;
    },
    set: function (val) {
      console.log('设置值')
      value = val
      Dep.trigger(tag, val)//调用发布
    }
  })
  // 绑定订阅(必须先订阅才能出发)
  Dep.listen(tag, function (text) {
    el.innerHTML = text
  })
}
  • 双向数据绑定/v-modle:初始化:设置输入目标值给dom更新时:监听dom,dom变化就修改目标值
  • 除了v-modle还可以怎么实现双向数据绑定:complute/watch

#MVC/MVVM/MVP

软件架构设计模式

  • MVC
# 组成:模型—视图—控制器
# 特点:Model 频繁发生变化,需要主动操作dom更新到View;
  • MVVM
# 组成:Model、View、ViewModel(View 和 Model双向绑定);
# 特点:Model 和 ViewModel 之间的交互是双向的;不需要手动操作DOM;使view也具有控制功能

# 缺点:1.虽然使用Model方便了保证数据一致性,但是大的模块中长期不释放内存就会内存压力
# 缺点:2.数据双向绑定不利于View层的代码复用
  • MVP
# 组成:模型—视图—控制器(Presenter)
# 特点:view和Model的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部

#单页面/多页面区别

补充区别:单页面只有一个index,多页面有多个index;

image-20230317131239767

#SPA缺点优化

  • seo优化:prerender-spa-plugin、vue-meta-info
# 安装预渲染插件 prerender-spa-plugin
# 解决title、描述、关键词插件: vue-meta-info
  • 首屏加载优化

补充:首屏变白的原因:第一次返回空的html,数据好了再返回真实页面数据

为什么做ssr:1、vue的首屏加载慢、2、不利于seo优化(代码都在js里面)

# 首屏SSR(服务端预渲染-骨架屏):通过nuxt.js;首屏服务端渲染,其他交互采用客服端渲染

#SSR

ssr:服务端预渲染;将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回客户端

  • 优点:利于seo、首屏加载优化
  • 缺点:只支持beforeCreate和created两个钩子;
# 1.组件化
# 2.数据驱动:没有虚拟dom的时候一个li变化,整个都更新,造成性能浪费

#diff中patch

两个阶段:初始化、更新

  • 初始化:虚拟dom转真实dom
// 1.需要三要素:虚拟节点、属性、子节点
// 2.创建dom、添加属性、创建目标节点,子元素加入到目标上(递归)
function vnode_to_dom(vnode) {
  // 三要素
  let tag = vnode.tag
  let attrs = vnode.attrs
  let children = vnode.children
  if (!tag) return null
  // 创建目标节点
  let dom = document.createElement()
  // 目标节点添加属性
  for (let attrsName in attrs) {
    if (attrs.hasOwnProperty(attrsName)) dom.setAttribute(attrsName, attrs[attrsName])
  }
  // 子元素加入目标
  children.forEach((childNode) => {
    dom.appendChild(vnode_to_dom(childNode))
  });
  return dom
}
  • 更新时:对比,老的虚拟节点-vdom、新的虚拟节点-vdom,当目标不一样就替换

#vue过滤器

  • 作用:常用于文本的格式化
filters:{
    upper(input){
        return input.slice(0,1).toUpperCase()+input.slice(1)
    }
}

#保存当前页面状态

  1. LocalStorage / SessionStorage
  2. 路由传参
  3. vuex
  4. keep-alive来缓存页面:当组件在keep-alive内被切换时组件的activated,deactivated

#事件修饰符

  • .stop :等同于js中的event.stopPropagation(),防止事件冒泡;
  • .capture:与事件冒泡的方向相反,事件捕获由外到内;
  • .self:只会触发自己范围内的事件,不包含子元素;
  • .prevent:等同于js中的event.preventDefault(),防止执行预设的行为;
  • .once:只会触发—次。

#v-for/key

优先级;v-for>v-if;所以不能同时用

  • v-for为什么要有key
# key是虚拟DOM对象的标识,vue在patch过程中通过key判断是否是同一个dom,使patch过程更快/更高效
  • v-for用index作为key可能会引发的问题
# 1 不管数组顺序如何改变,index都是从0、1、2..这样排列;会导致操作错误节点
# 2 同级元素也使用v-for以index作为索引会报错
  • vue2中v-for优先于v-if被解析,如果同时出现,每次渲染都会先执行循环再判断条件

#keep-alive缓存组件

  • 是什么:keep-alive包裹动态组件时,会缓存不活动的组件实例。
# 3个props属性:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
max - 数字。最多可以缓存多少组件实例

# 2个生命周期函数
activated()# 激活时,会重新调render;
deactivated()# 当组件被换掉时,会被缓存到内存中、触发deactivated生命周期
  • 如何使用
<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>
  • keep-alive为什么不能缓存 Iframe 中的 dom 结构
# 1 Vue的keep-alive缓存也是基于VNode节点而不是直接存储DOM节点。
# iframe页里的内容并不属于节点的信息,keep-alive依然会重新渲染iframe内的内容。
  • 缓存什么:虚拟节点vnode实例,缓存时进行对比
# 注意:路由表中的mate属性 配置哪些组件需要缓存;
meta:{ noCache: true //如果设置为true,则不会被 <keep-alive> 缓存(默认 false) }
  • LRU(least recently used)缓存策略:最近被访问,那将来被访问几率更高

#nextTick

nextTick:dom更新之后再延迟回调

  • 原理:基于事件循环,在主线程执行任务之前,先将任务放到一个消息队列里,等待主线程执行完毕后,取出执行
  • 应用场景:获取更新后的dom;this.$nextTick,场景操作页面,获取操作后的结果再操作

#Vue自定义指令

vue内置指令(v-show、v-text等..),不满足开发需要时,需要自定义指令;没有自定义过指令

#assets/static区别

  • 打包前后区别

  • 相同点:都是存放静态资源的

  • assets打包后到了dist的static中--进行了压缩、代码格式化

#delete/Vue.delete删除数组区别

  • delete:没有删除键,只是值变为undefined/null
  • Vue.delete:直接删除了数组

#vue初始化页面闪动

原因:页面一开始还没解析时加载到插值表达式

解决办法:在插件表达式的div加,v-cloak (隐藏元素,内存中替换)

出现场景:插值表达式

  • 解决办法:v-cloak渲染指令(解决屏幕闪动)
<p class="#app" v-cloak>
	<p>{{value.name}}</p>
</p>
<style>
    [v-cloak] {
        display: none;
    }
</style>

v-cloak原理:隐藏元素、在内存中进行值替换,完成后v-cloak 属性会被自动去除

#extend

作用:**扩展组件生成—个构浩器,**通常会与$mount一起使用。

概念:基于Vue构造器创建一个Vue子类,对Vue构造器进行扩展,通常会与$mount一起使用。

image-20230322225210908

#父/子组件执行顺序

  • 加载渲染过程:

1.父组件 beforeCreate2.父组件created3.父组件 beforeMount4.子组件 beforeCreate5.子组件created6.子组件 beforeMount

7.子组件 mounted8.父组件mounted

  • 更新过程:

1.父组件beforeUpdate2.子组件beforeUpdate3.子组件updated4.父组件updated

  • 销毁过程:

1.父组件beforeDestroy2.子组件 beforeDestroy3.子组件destroyed4.父组件destoryed

更新和销毁相似

#created/mounted区别

  • created 模板渲染html前调用
  • mounted 模板渲染成html后调用。通常是确定dom已经生成,再操作dom,例如echarts画图

#什么生命周期请求异步数据

  • 在created、beforeMount、 mounted 此时的data已经创建;
  • 推荐created异步请求数据,SSR只支持beforeCreated、created,方便统一建议created,

#组件传参

  • 父子传参:props、$emit
# 父传子:v-ind绑定一个值,子组件通过props接收
# 子传父:$emit('xxx',value),父组件通过@方法,接收传来的变量xxx
  • 任意传参:事件总线eventBus($emit / $on)
# 两页面都引入EventBus
# 发:EventBus.$emit("addition',xxx)
# 收:EventBus.$on("addition',function(xxx){})
  • 祖孙传参:(provide/ inject)
// 爷
provide() {
    return {
        num: "xxx"
    }
};
// 孙
inject:['num']
  • vuex:略
# 存:store.commit('theme/setTheme', obj)
# 调:store.state.theme.theme

#vue-router路由

  • vue-router原理
# hash原理:onhashchange 事件(监测hash值变化),可以在 window 对象上监听这个事件。
# history原理:pushState() 和 replaceState() 方法
  • 路由模式三种:hash、history

  • 使用路由模块来实现页面跳转

# 1 直接修改地址栏
# 2 router.push(‘路由地址’)
# 3 router-link
  • Vue-Router的懒加载如何实现
# 使用箭头函数+import动态加载
# 使用箭头函数+require动态加载
  • 路由的hash和history模式的区别

hash改变不会请求服务器、history需要正确配置nginx

# hash: 会有#,又称前端路由
# hash原理:onhashchange()事件,hash值发生变化时无需向后端发起请求
# history:没有#
# history模式需要nginx配置支持。如果nginx没有正确配置,访问时会返回404。
history.go(-2);//后退两次
history.go(2);//前进两次
history.back(); //后退
hsitory.forward(); //前进
  • 如何获取页面的hash变化
# 方法1:监听$route属性;onhashchange
# 方法2:window.location.hash 读取hash值
  • $route和$router的区别
# router路由实例:router.push路由跳转的方法
# route路由信息对象:包含路由信息query、params、path、name
router.push({path:'/home', params:{id:'12'}}) 	# 用来跳转传参
route.query.id route.params.id 					# 用来获取参数信息
  • 如何定义动态路由?如何获取传过来的动态参数?

params类似post,地址栏不显示参数,query类似get,地址栏出现参数

param传参

(1) param方式
# 配置路由格式:/router/:id
# 传递的方式:在path后面跟上对应的值传递后形成的路径:/router/123
(2)路由跳转
# to可以是name或者path
# router.push({path:'/home', params:{id:'12'}}) router.push({path:'/home/:1')

query传参

(1) query方式
# 配置路由格式:/router 正常配置
# 传递的方式:在path后面跟上对应的值传递后形成的路径:/router?id=123
(2)路由跳转
# to可以是name或者path
# router.push({path:'/home', query:{id:'12'}}) router.push({path:'/home/:1')
  • vue-router路由钩子在生命周期的体现

三个全局路由钩子:前置路由、解析路由、后置路由

# router.beforeEach 前置路由
# router.beforeResolve 解析路由 beforeRouteEnter调用之后调用
# router.afterEach 后置路由

三参数:to、from、next()

# to 去哪
# from 来着哪
# next() 允许从to到from
  • vue-router跳转和location.href有什么区别
localtion.href
# 会刷新页面(场景:跳外链)
vue-router
# 1.按需加载,减少dom操作(场景:内部页面)
# 2.js原生,history.pushState,无需刷新页面、静态跳转
  • vue-router导航守卫有哪些
# 全局三钩子:beforeEach、beforeResolve、afterEach
# 路由独享的守卫: beforeEnter
# 组件内的守卫: beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

#vuex

  • Vuex中action和mutation的区别
action 异步操作、不能直接改变状态,需要通过上下文提交mutation;场景:多个任务时的异步操作修改状态
# store.dispatch('user/sum_actions', sum) // 含有异步操作,数据提交至 actions;
mutation 同步操作,是改变状态的唯一方法
# store.commit('theme/setTheme', obj) // 同步操作,数据提交至 mutations;修改store的state的值
  • vuex和localStorage的区别
# 1 vuex存在内存中,刷新页面消失;localStorage存在浏览器中,一直存储;但是读取内存比读硬盘快
# 2 vuex能做响应式数据,localStorage不能
  • vuex有哪几种属性?
state # 基本数据
getters # 基于基础数据派生的数据
muations # 改变状态的唯一方法;commit
actions # 异步操作、调muations
modules # 模块化
  • Vuex和单纯的全局对象有什么区别
# 主区别:状态管理(vuex由统一的方法修改数据,全局变量可以任意修改)、响应式数据
  • 为什么Vuex的mutation中不能做异步操作方便跟踪状态
  • Vuex的严格模式是什么,有什么作用,如何开启?

概念:状态变更且不是由 mutation 函数引起的,将会抛出错误

const store = new Vuex.Store({
    strict :true,
})
  • Vuex 区分 State 外部修改、内部修改(commit)

修改state唯一渠道就是commit;监听_committing 是否为true

#vuex/pinia区别

# 1 抛弃了Vuex中的Mutation
# 2 pinia中action支持同步和异步,Vuex的action是异步
# 3 支持服务端渲染ssr

#Updated可以修改节点嘛

能,但不推荐在updated钩子函数中直接修改DOM节点;更新dom或数据,对于不定的数据会触发死循环

补充:不要在update beforeUpdate修改不定数据,否则会引起死循环

#vue限制传递数据的类型

在props中限制传递类型type、值是否必须required、default默认值

props: {
    test: {
        type: Number, // 数字类型
        required: true // 是否必须
        default: 99 // 默认值
    },
},

#attribute/property区别

  • property是DOM中的属性,是js对象

  • attribute是HTML标签上的特性,它的值只能够是字符串

下面获取/修改值的区别:以获取class为例

let div1 = document.getElementById('div1');// 获取div节点
# attribute取值:div1.getAttribute('class');
# attribute修改值:div1.setAttribute('class', 'xxx')

# property直接取值:div1.xx
# property直接修改值:div1.xx = 'xxx'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蹦卡啦撒卡玛卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值