-
watch 和 computed 的区别
- watch 是监听,支持异步操作,内部有 immediate、deep、handle三个属性,当一条数据影响多条数据时,使用 watch ,常见的就是搜索
- computed 是计算属性,能够缓存,内部是 getter、setter 方法,当归一个属性受多个属性影响时调用计算属性,典型的案例就是购物车商品结算
-
Vue2 的生命周期函数
- beforeCreate:创建之前
- create:创建完成
- beforeMount:挂载之前
- mounted:挂载完成
- beforeUpdate:更新之前
- updated:更新完成
- beforeDestroy:销毁之前
- destroyed:销毁完成
- activated:激活时触发
- deactivated:未激活时触发
- beforeRouteEnter:组件路由进入之前,渲染之前
- beforeRouteUpdate:组件路由更新
- beforeRouteLeave:组件离开当前路由是调用
-
Vue通信方式
- vuex:状态管理仓库
- eventbus:中间件 bus
- 父子组件:子组件使用 props 接收数据
- 子父组件传值:子组件使用 $emit 派发事件传参,父组件调用事件接收参数
- 作用域插槽:父组件使用 slot-scope 接收子组件数据
- 跨组件传值:inject、provider
- $ref
- 路由 $router 可以传值
- sessionStorage、localStorage
-
Vuex是什么
- Vuex 是 Vue 的状态管理工具
- 它有五大核心:
- state:存储数据
- getters:计算属性
- mutations:同步提交更改数据的方法
- actions:异步提交一个 mutation 给 mutations
- modules:模块化
-
axios 的封装
- 导入 axios 的依赖,使用 axios.create 创建一个 axios,里面设置 baseURL、timeout、响应头等,baseURL 设置 process.env + 路径,process.env 会根据你是用的是 npm run build / serve,来判断你是编译环境还是上线环境,然后补齐路径。
- 之后可以设置一个请求拦截器和响应拦截器,请求拦截器可以判断 token 来做进一步操作,而响应拦截器可以根据响应的状态码进行不同的操作。
- 最后再创建一个文件,里面暴露出需要调用的一些 API 接口。
-
Vue 中的插槽及作用
- 匿名插槽
- 具名插槽:有 name 值的插槽
- 作用域插槽:父组件使用 slot-scope 或者 scope 接收子组件传来的参数
-
v-show 和 v-if 的异同
- 两者都是控制元素显示隐藏的
- v-show 不会进行判断,而是直接渲染,主要控制的是元素的 display:none/ block,
- v-if 会先判断是否满足条件再渲染,主要是对元素的删除和重建
- 当切换较多的情况下使用 v-show,这样会减少页面的重回和回流,降低性能的消耗
-
keep-alive 的作用
- 在路由配置表中的 meta 的 keepAlive 属性,设置 true 表示需要被缓存
- 也可以使用 keep-alive 包裹需要被缓存的组件
- 它可以精确控制哪些组件需要被缓存
-
如何理解渐进式框架
- 你可以根据项目的需求和复杂性逐步引入 Vue.js 的不同部分。如果你只需要构建一个简单的页面,可以仅使用 Vue 的核心库。如果需要更复杂的功能,你可以选择引入 Vue 的路由库(如Vue Router)、状态管理库(如Vuex)或其他相关库。
- 这种渐进式的设计理念就是选项式 API
-
单页面的优缺点
- 只有一个页面,页面切换只是路由改变,并没有产生新的 html 页面
优点:
- 页面切换速度快
- 良好的交互体验
- 良好的前后端工作分离模式
缺点:
- 不利于 seo
- 首页加载慢
-
assets 和 static 的区别
- 两者都可以用来存放静态资源
- assets 存放的静态资源在项目打包时,会进行压缩,最后存放在 static 中一起上传
- static 存放的静态资源不会被压缩
-
Vue 中常见的修饰符
- .stop:防止事件冒泡
- .prevent:防止执行预设的行为
- .capture:与事件冒泡的方向相反,事件捕获由外到内;
- .self:只会触发自己范围内的事件,不包含子元素;
- .once:只会触发一次。
-
封装过 Vue 组件吗?说下封装思路
- 把基础模板搭建好
- 准备好需要传入的数据,例如 props 传的数据类型、默认值等,还要考虑是否需要插槽或者回调函数来传值
- 准备好输出的数据,做好需要暴露出的方法
- 封装完毕,直接调用
- axios 的二次封装、分页组件的封装、按钮组件的封装、轮播图组件封装等等
-
初始化页面闪动问题如何解决?
- 是因为代码还没有解析,所以一般会出现花屏的问题
- 在 css 中加上:[v-cloak] { display: none}
- 在根元素上加上:style="display: none"
-
hash 路由和 history 路由
- hash 路由地址栏带 #,兼容性好
- history 路由稍微好看一点
-
Mixin 的使用场景
- Vue 的 Mixin 可以将一些通用的代码逻辑封装在 Mixin 中,并在需要时混入到多个组件中,可以提高代码的可维护性和复用性。采用策略模式针对不同的属性进行合并。 如果混入的数据和本身组件的数据有冲突,采用本身的数据为准。
- 缺点:命名冲突、数据来源不清晰
// 定义一个mixin对象 const myMixin = { data() { return { message: 'Hello, mixin!' }; }, methods: { showMessage() { console.log(this.message); } } }; // 在组件中使用mixin Vue.component('my-component', { mixins: [myMixin], created() { this.showMessage(); // 调用mixin中的方法 } });
-
Vue 中组件的 data 为什么是一个函数
- 防止两个组件的数据污染
- 如果都是对象的话,会在合并的时候,指向同一个地址。 而如果是函数的时候,合并的时候调用,会产生两个空间。
-
Vue 为什么要使用虚拟 DOM
- 虚拟 DOM 是模拟真实 DOM 的一个 JS 对象,
- 频繁操作真实 DOM ,会造成大量的重绘和回流,降低性能
- 使用虚拟 DOM 可以减少重绘和回流,而且 虚拟 DOM 不依赖真实平台环境,可以实现跨平台
-
Diff 算法原理
Vue的 diff 算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式+双指针方式比较
- 先比较两个节点是不是相同节点
- 相同节点比较属性,复用老节点
- 先比较儿子节点,考虑老节点和新节点儿子的情况
- 优化比较:头头、尾尾、头尾、尾头
- 比对查找,进行复用
-
谈谈对组件的理解
- 组件可以看作是封装了特定功能和样式的可重用代码块,它将相关的数据、模板和逻辑组织在一起,以创建独立、可复用和可组合的部件。
- 组件化开发能大幅提高开发效率和复用性
- 降低更新范围,只需要渲染改变的组件
- 高内聚、低耦合、单向数据流
-
什么是单向数据流和双向数据绑定
单向数据流:数据的流向是单向的,数据修改影响视图,视图改变不会修改到数据中
双向数据绑定:数据流相是相通的,数据修改影响视图,视图改变了也会影响到数据
-
对比 JQuery,Vue 有什么不同
- JQuery 专注视图层,通过操作 DOM 去实现页面的一些逻辑渲染;
- Vue 专注于数据层,通过数据的双向绑定,最终表现在 DOM 层面,减少了 DOM 操作。Vue 使用了组件化思想,使得项目子集职责清晰,提高了开发效率,方便重复利用,便于协同开发
-
对 Vue 项目进行性能优化
代码优化:
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分使用场景
- v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- 长列表使用虚拟列表性能优化
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件的按需引入
- 使用 keep-alive 缓存
- 防抖、节流等
Webpack 层面的优化:
- 提取公共代码
- 使用 Webpack 对图片进行压缩
- 模板预编译
-
Vue3 的特性
- 使用 Proxy 进行数据劫持,可以监听属性的添加和删除,能监听数组
- 新增了 13 apply、ownKeys、deleteProperty、has 等拦截方法
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的
- Vue3 使用组合式 API ,利于逻辑的并和、提高了开发效率和偏于维护
- 更好的支持 TypeScript
- 重写了虚拟 DOM,提高了渲染性能
-
Vue 的内置指令
- v-once :元素或组件只渲染一次
- v-cloak :等待编译完再渲染
- v-bind :绑定属性,可以简写为 ‘ :’
- v-on :事件绑定,可以简写为 ‘ @ ’
- v-html :相当于 innerHTML ,注意防止xss攻击
- v-text :相当于 innerText
- v-model :数据双向绑定,绑定 value 值
- v-if / v-else / v-else-if:条件判断执行渲染。
- v-show :控制 display 来进行显示隐藏
- v-for :循环渲染,需要绑定 key 值
- v-pre :跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度。
- v-text :相当于 innerText
- v-once :只编译一次
-
为什么 v-for 和 v-if 不一起使用
- 会导致性能问题和渲染顺序的问题
-
Vue2 响应式数据的原理
- 整体思路是数据劫持 + 观察者模式
- 使用 Object.defineProperty 将属性进行劫持,数组则是通过重写数组来实现。
- 使用 getter 收集依赖 ,当依赖变化后 watcher 侦听器会监听到,然后通知 setter 派发更新
-
Vue 的父子组件生命周期钩子函数执行顺序
加载渲染过程:
- 父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程:
- 父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程:
- 父 beforeUpdate -> 父 updated
销毁过程:
- 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
-
Vuex 页面刷新数据丢失怎么办
- 使用 localStorage 本地存储
- 第三方插件 vuex-persist
-
Vuex 为什么要分模块并且加命名空间?
- Vuex 的模块化和命名空间是为了更好地组织和管理状态,解决状态命名冲突和模块耦合的问题。
-
Vue 中使用了哪些设计模式
- 单例模式:整个程序只有一个实例
- 发布者订阅者模式
- 装饰器模式:插槽
- 工厂模式:vue.component
- 组合模式:use 和 install
-
params 传参和 query 传参的区别
- params 传参,参数直接写在 url 后面
- query 传参,参数以 ?拼接,传参形式是键值对
- query 传参不会产生丢失问题,因为它会缓存数据,params不会缓存,所有页面重新编译的时候,会产生数据丢失的问题
- 要解决 params 传参丢失的问题,要指定对应的 path 路径,通过’ :名字 ’来规范对应的接收的数据的 key
-
如何样式穿透
- stylus 样式穿透使用:>>>
- sass 和 less 使用:/deep/
- 通用使用: ::v-deep
- !important