一:VUE组件之间通信方式有哪些(8.2)
- 父子组件通信:父通过 props 将数据给子,子通过 $emit 触发事件将数据给父
- 子父组件通信:子通过 $emit 触发事件将数据给父,父通过 $refs 获取子的实例并调用其方法
- 兄弟组件通信:可以通过一个公共的父作为中介,将数据传递给父,在通过 props 传递给另一个兄弟
- 使用事件总线
- 使用 vuex
- 使用 $emit 和 $on
二 v-if和v-for那个优先级最高(8.3)
- vue2中 v-for 比 v-if 优先级更高一些,vue3相反
三 简述vue的生命周期及每个阶段做的事(8.3)
vue2 | vue3 | 描述 |
beforeCreate | beforeCreate | 在实例初始化后,数据观测和事件配置之前调用,这个阶段,实例的属性和方法还没有被初始化 |
create | create | 在实例创建完之后调用,在这个阶段,实例属性和方法已经初始化,但是DOM元素还没有挂载,无法访问DOM元素 |
beforeMount | beforeMount | 在挂载开始之前调用。在这个阶段,vue将编译模板生成虚拟DOM,并准备将其渲染到页面上 |
onBeforeMount | 在挂载之前调用。在这个阶段,虚拟DOM已经生成,但还没渲染到页面 | |
mounted | mounted | 在挂载完成后调用。在这个阶段,vue将虚拟DOM渲染成真实的DOM,并挂载到页面上,在这个阶段可以访问到DOM元素,可以进行DOM操作 |
onMounted | 在挂载完成后调用。在这个阶段,可以进行一些需要访问到DOM操作 | |
beforeUpdate | beforeUpdate | 在数据更新之前调用。这个阶段,vue将重新渲染虚拟DOM,并准备将其更新到页面上 |
onBeforeUpdate | 在数据更新之前调用。这个阶段,可以进行一些数据更新前操作 | |
updated | updated | 在数据更新完成后调用。在这个阶段,vue将更新虚拟DOM,并将更新后的内容渲染到页面上。在这个阶段,可以访问到更新后的DOM元素,可以进行DOM操作 |
onUpdated | 在数据更新完成后调用,在这个阶段,可以进行一些需要访问到更新后的DOM操作 | |
beforeUnmount | beforeUnmount | 在实例销毁之前调用,这个阶段,实例还没有销毁,可以进行一些清理工作 |
onBeforeUnmount | 在实例销毁之前调用,在这个阶段,可以进行一些清理工作 | |
unmounted | unmounted | 在实例销毁完成后调用,这个阶段,实例已经销毁,所有的事件监听和定时器都已经移除 |
activated | activated | 在缓存组件被激活时调用,当缓存组件从非活动状态切换到活动状态时,会触发activted生命周期钩子函数。在这个阶段,可以执行一些需要组件激活时执行的操作 |
deactivated | deactivated | 在缓存组件被停用时调用。当缓存组件从活动状态切换到非活动状态时,会触发deactivated钩子函数 |
errorCaptured | errorCaptured | 在子组件发送错误时被调用,可以用来捕获和处理子组件的错误 |
renderTracked | 在组件的渲染追踪阶段被调用。可以用来监控组件的依赖追踪情况 | |
renderTriggered | 在组件的渲染触发阶段被调用。可以用来监控组件的重新渲染情况 | |
serverPrefetch | 在组件实例化之前调用,用于在服务器渲染期间预取数据,可以用来获取组件所需的异步数据 |
四 说说vue2和vue3的双向绑定使用和原理及区别(8.4)
- 使用
- vue2使用v-model指令来进行表单元素的双向绑定,使用双花括号{{}}进行数据绑定
- vue3拥有vue2的方法且引入了Composition API,其中reactive和ref函数可以用来创建响应式数据。reactive函数可以将一个普通对象转换为响应式对象,ref函数可以将一个普通值转换为响应式对象
- 原理:
- vue2使用数据劫持和观察者模式;在vue2内部,通过使用Object.definproperty方法来劫持对象的属性,当属性值发生变化时,会触发响应的更新操作、同时,vue2也使用了观察者模式,通过创建观察者对象来监听数据的变化,并且在数据变化的同时去通知相关的视图进行更新
- vue3使用Proxy代理对象:vue3使用了Proxy对象来实现对数据的劫持,Proxy对象可以拦截对对象的访问和操作,从而实现对数据的监听和响应。
五 如何扩展一个组件(8.5)
- vue2可以使用mixins和继承
1.使用mixins是一种重用组件的逻辑方式。 // 定义一个mixin对象 let myMixin = { created: function () { console.log('Mixin created') }, methods: { greet: function () { console.log('Hello from mixin') } } } // 创建一个组件,并混入mixin Vue.component('my-component', { mixins: [myMixin], created: function () { console.log('Component created') }, methods: { greet: function () { console.log('Hello from component') } } }) 2.使用继承:可以创建一个新的组件,并继承要扩展的组件 // 定义一个父组件 let ParantComponent = Vue.extend({ created: function () { console.log('parant component created') }, methods: { greet: function () { console.log('Hello from parant component') } } }) // 创建一个子组件,并继承父组件 let ChildComponent = ParantComponent.extend({ created: function () { console.log('child component created') }, methods: { greet: function () { console.log('Hello from child component') } } }) // 注册子组件 Vue.component('my-component', ChildComponent)
- vue3使用组合式API和继承
1.使用组合式API: // 创建一个自定义的Component APi函数 function userCustomLogic () { console.log('custom logic') return { greet: function () { console.log('Hello from custom logic') } } } // 创建一个组件,并使用自定义 Component API函数 Vue.component('my-component', { srtup() { const {greet} = userCustomLogic() returun { greet } } created() { console.log('component created') } }) 2.继承,和vue2相同
六 子组件可以直接改变父组件的数据吗?(8.7)补8.6
- 子组件默认情况下是不能修改父组件的数据的,这是因为vue遵循了单向数据流的原则,父组件通过props传递给子组件,子组件只能读取不能修改
- 如果要修改父组件的数据,可以通过以下两种方式
- 使用事件(event)
- 父组件可以在子组件绑定一个自定义事件,并在子组件中触发该事件
- 子组件通过$emit方法触发该事件,并传递需要修改的数据作为差数
- 父组件监听子组件触发的事件,并在事件处理函数中修改组件相应的数据
- 使用vuex:
- 将需要共享的数据存储在vue状态管理中
- 子组件通过调用vuex中mutations方法来修改数据
- 父组件和子组件都可以通过访问vuex中的数据来获取最新的状态
- 使用事件(event)
七 vue2和vue3响应式的理解(8.7)
- vue2的响应机制是通过object.defineProperty()方法来实现的。当一个对象被传入vue实例的data选项中时,vue会遍历该对象的所有属性,并使用object.defineProperty()方法将这些属性转换为getter和setter。这样,当属性被修改时,vue能够捕捉到,并触发响应的更新
- vue3采取了proxy对象来实现。proxy对象可以拦截目标对象的访问和修改,并在拦截到操作时触发相应的操作
- vue3相对于vue2的优势
- 性能优化
- 更好的类型推导
- 动态添加和删除属性的支持
八 vue的路由实现: hash模式 和 history模式(8.8)
- hash模式:
- 在hash模式下,url的路由会以#符号开始
- 在这种模式下,路由的改变不会触发浏览器的刷新,而是通过监听hashchange事件来实现路由的切换
- vue router默认使用hash模式作为路由
- history模式
- 在此模式下,url的路由不会有#符号
- 在此模式下下,路由会通过改变HTML5的history.pushState和history.replaceState方法来修改URL,但不会触发页面的刷新
- 为了支持history,服务器需要配置,以确保在刷新页面或直接访问路由时能够正确地返回相应的页面
九 vue路由钩子函数(8.9)
- beforeEach:在每个路由切换之前调用,可以用来进行全局的导航守卫
- beforeResolve:在每个路由切换之前调用,但在组件内的守卫之后调用。用于确保异步路由组件被解析完成
- afterEach:在每个路由切换之后调用,可以用来进行一些全局 后置处理逻辑
- 组件的路由守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。用来处理组件内部的路由变化逻辑
十 vuex是什么? 哪种功能场景使用它?(8.10)
- vuex是一个转为vue.js应用程序开发的状态管理程序
- 核心概念包括:
- state:存储应用程序的状态数据
- getters:从状态中派生出新的状态,类似于计算属性
- mutations:修改状态的唯一途径,必须是同步函数
- actions:修改mutations,可以包含异步操作
- modules:将vue分割成模块,每个模块拥有自己state,getter,mutations和action
- vuex常用场景
- 多个组件共享状态
- 多个组件之间的通信
- 复杂的状态逻辑
十一 $route 和 $router 的区别(8.11)
- $route:
- 是一个只读的对象,用于获取当前路由的信息
- 他包含了当前的路由,参数,查询参数,路由名称等信息
- 可以通过$route.push获取当前路由的路径,通过$route.params获取路由参数,通过$route.query获取查询参数等
- $router
- 是一个路由实例,用于进行路由的导航操作
- 它包含了一些方法,如 push,replace,go 等,用于进行路由的跳转和导航
- 可以通过$router.push方法进行路由跳转,$router.replace进行路由替换,$router.go方法进行路由的前进和后退
- 区别
- $route是一个只读对象,用于获取当前路由的信息
- $router是一个路由实例,用于进行路由的导航操作
十二 <keep-alive></keep-alive> 的作用是什么?(8.12)
- 用于在vue组件之间缓存和保持状态
- 特点:
- 缓存组件实例:当组件被包裹在<keep-alive>中,组件实例不会销毁,而是被缓存了,这样在组件切换时,可以直接使用缓存的组件实例,而不需要从新创建
- 保持组件状态:缓存的组件会保持其状态,包括数据,DOM状态等。这样在组件切换时,可以保持之前的状态,而不需要重新初始化
- 生命周期钩子:缓存的组件实例会触发一些特定的钩子函数,例如activeted和deactiveted,这些钩子函数可以用来在组件缓存和激活时执行一些特定的逻辑
十三 v-el的作用是什么(8.14)补8.13
在vue中已经被废弃了,不在推荐使用。由ref属性替代
十四 vue-cli 工程技术集合介绍(8.14)
- webpack:打包工具
- babel
- Eslink
- vue Router
- vuex
- CSS预处理器
- 单元测试和端到端测试
- 插件系统
十五 nextTick(8.15)
- 是一个异步方法,用于DOM更新之后执行的函数。它的作用是在下次DOM更新循环结束后执行指定的函数,可以获取更新后的DOM
- 使用方法
// 1.作为实例使用 this.$nextTick(() => { // 在DOM更新之后执行的回调函数 }) // 2.作为全局方法使用 Vue.nextTicl(() => {})
十六 vue的优点是什么?(8.16)
- 简单易学
- 响应式数据绑定
- 组件化开发
- 轻量高效
- 生态系统丰富
- 渐进式框架
十七 路由之间跳转?(8.17)
// 1
<router-link to="/about">Go to About</router-link>
// 2
this.$router.push('/about');
十八 实现 Vue SSR(8.18)
- 是指在服务器端将vue组件渲染成HTML字符串,然后将该字符串发送给客户端进行展示。
- 步骤
- 创建vue实例
- 创建渲染器
- 渲染组件
- 返回HTML字符串
- 简单示例
// 1. 创建Vue实例 const Vue = require('vue'); const app = new Vue({ template: '<div>Hello {{ name }}</div>', data: { name: 'Vue SSR' } }); // 2. 创建渲染器 const { createRenderer } = require('vue-server-renderer'); const renderer = createRenderer(); // 3. 渲染组件 renderer.renderToString(app, (err, html) => { if (err) { console.error(err); } else { // 4. 返回HTML字符串 console.log(html); } });
十九 vue 组件 data 为什么必须是函数(8.21)
- 因为vue组件可以被复用很多次,每个实例都需要拥有独立的数据对象
- 当data选项是一个对象,所有组件实例将共享同一个数据对象,这样会导致一个组件的数据变化会影响到其他组件实例的数据。
二十 vue computed 实现(8.22)
- computed属性来实现计算属性,它是 一个函数,他会依赖的数据动态计算出一个新的值,并将这个值缓存起来,只有当依赖的数据发送变化时,才会重新计算
- 建立与其他属性的联系