前端面试复习干货
一、什么是跨域?
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
这里说明一下,无法跨域是浏览器对于用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题了。是浏览器的锅,对。
同源策略限制了一下行为:
Cookie、LocalStorage 和 IndexDB 无法读取
DOM 和 JS 对象无法获取
Ajax请求发送不出去
二、ajax请求原理?
通过浏览器内置对象xmlHttpRequest向服务器端发送数据,然后通过js操作dom实现数据刷新。
三、盒模型
一个盒子中主要的属性就5个:width、height、padding、border、margin。如下:
- width和height:内容的宽度、高度(不是盒子的宽度、高度)。
- padding:内边距。
- border:边框。
- margin:外边距。
标准盒模型: width 不包含border padding
ie盒模型: width 包含border padding
四、深拷贝和浅拷贝的区别 (只针对引用数据类型)
1、浅拷贝
// 浅拷贝
var arr = [1,2,3,4]
arr1 = arr
arr[0] = 0;
console.log(arr,arr1)
改变arr的同时arr1也发生了改变这就是浅拷贝
2、深拷贝
var arrList = [1,2,3,4,{"list":[1,2,3,4,6]}]
// 深拷贝(针对引用数据类型的拷贝)
// 方法一 deepClone(arrList)就是拷贝的新数组
function deepClone(obj){
// 判断是对象还是数组并创建一个空的来承接
var arr = Array.isArray(obj)?[]:{};
// 如果属于对象的话
if(obj && typeof obj === 'object'){
for(key in obj){
// 如果对象中含有私有属性
if(obj.hasOwnProperty(key)){
//判断obj子元素是否为对象,如果是,递归复制
if(obj[key] && typeof obj[key] === 'object'){
arr[key] = deepClone(obj[key])
}else{
arr[key] = obj[key]
}
}
}
return arr
}
}
console.log(deepClone(arrList))
// 方法二 newArrList就是拷贝的新数组
var newArrList = JSON.parse(JSON.stringify(arrList))
四、什么是继承?
JS继承的实现方式:
// 定义一个动物类
function Animal (name) {
// 属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + '正在吃:' + food);
};
1、原型链继承
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
2、构造继承
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
3、实例继承
function Cat(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
4、拷贝继承
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
this.name = name || 'Tom';
}
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
5、组合继承
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
6、寄生组合继承
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
Cat.prototype.constructor = Cat;
五、节流和防抖
- 防抖:举个例子当屏幕滚动的时候会持续的触发scroll事件但是如果设置了防抖的话,如果我设置防抖时长是一秒的话,我会在scroll事件触发后一秒的时候执行,如果我再次触发scroll事件时间又会重新计算
- 节流:举个例子当屏幕滚动不停的触发scroll事件的时候,我会每隔一秒执行以下不管scroll触发多少次我都会一秒以后执行一次
六、闭包
闭包的特点
- .函数嵌套函数,内部函数可以引用外部函数的参数和变量
- 参数和变量不会被垃圾回收机制所收回
闭包的好处
- 变量长期保存在内存当中
- 避免变量被全局环境污染
function fnAn(){
var a = 1;
return function(){
return a
}
}
var a = fnAn()
console.log(a())
七、链式调用
这个很容易理解,例如:
$('div').setStyle('color', 'red').show();
function fn(){
this.age=28;
this.name='行走的五花肉'
this.work = function(){
console.log(this.age)
return this;
}
this.like = function(){
console.log(this.name)
return this;
}
}
var tellMsg = new fn();
//一般的函数调用
// tellMsg.work()
// tellMsg.like()
//链式调用
tellMsg.work().like()
一般的函数调用和链式调用的区别:链式调用完方法后,return this返回当前调用方法的对象。
优点是:简化代码,让代码更加简洁、易读,同时也避免多次重复使用一个对象变量
八、同步和异步
参考文献:
JS 是单线程,你了解其运行机制吗 ?
关于setTimeOut和Promise执行顺序的问题
知识点:宏任务(macrotask)和微任务(microtask)
- 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
- 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
异步任务包括宏任务和微任务,宏任务的优先级高于微任务
九、递归
函数自身调用自身就是递归具体可以参考js原生深拷贝的方法
十、冒泡排序
function guLuSort(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
// 相邻元素两两对比,元素交换,大的元素交换到后面
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
//使用函数
console.log(guLuSort([34, 18, 27, 19, 35]))
相邻两个元素进行比较如果前一个元素大那么就交换位置
十一、块级格式化上下文
参考文献:块级格式化上下文
具有BFC属性的元素也属于普通流定位方式,与普通容器没有什么区别,但是在功能上,具有BFC的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且具有普通容器没有的一些特性,比如包含浮动元素,以防止出现高度塌陷问题。
如何触发BFC
- 浮动元素:float除none以外的值
- 绝对定位元素:position(absolute、fixed)
- display为以下其中之一的值inline-block、flex、inline-flex、table-cell、table-caption
- overflow除了visible以外的值(hidden、auto、scroll)
十二、常见兼容问题
- Ie盒模型和标准盒模型不同
- 块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大
- 设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度
- 行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug
- 图片默认有间距
- 标签最低高度设置min-height不兼容
- 透明度的兼容CSS设置
十三、this指向问题
谁调用它指向得就是谁(是否有调用者),无调用者默认是window
//this指向问题
var num = 10;
function test() {
console.log(num);
num = 100;
console.log(this.num);
var num;
console.log(num);
}
test(); //undefined、10、100
//undefined 因为num = 100变量提升了所以是undefined
//10 因为没有对象调用test()方法,this指向window.输出10
//100
十四、vue中key的作用
key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
最常见的用例是结合 v-for:
<ul>
<li v-for="item in items" :key="item.id">...</li>
</ul>
它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
- 完整地触发组件的生命周期钩子
- 触发过渡
例如:
<transition>
<span :key="text">{{ text }}</span>
</transition>
当 text 发生改变时, 总是会被替换而不是被修改,因此会触发过渡。
十五、call bind apply的区别
call apply不仅改变this指向,而且会调用函数
bind只是改变了this但是函数并不会执行
十六、如何解决vue打开白屏时间过长的问题?
1.路由懒加载
2.cdn引入外部资源
3.图片用网图
4.修改config里面的sourcemap属性
十七、二维数组转一维数组?
参考链接:二维数组转一维数组的多种方法
var erwArr = [1, 2, 3, [4, 5, 6],[10, 12, 33]]
//es5写法
function resArray1(arr){
return [].concat.apply([],arr)
}
console.log(resArray1(erwArr))
//es6写法
function resArray(arr) {
return [].concat(...arr.map((item)=>Array.isArray(item)?resArray(item):item))
}
console.log(resArray(erwArr))
十八、如何优化vue运行过慢,打包完以后体积过大的问题
十九、双飞翼布局和圣杯布局
中间固定两边自适应,双飞翼是借住margin-left负数 圣杯布局是借住position relative
二十、事件冒泡和事件捕获通过什么节点传递的
二十一、vue路由的几种模式?
hash模式、history模式以及两者的区别
VUE.js常问考点
vue的基本原理是什么?(出自:https://cn.vuejs.org/v2/guide/reactivity.html)
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
1、vue页面传递参数有几种方式?
方式1:query传参的方式 (特点:刷新页面参数不丢失)
方式2:params传参的方式 (特点:刷新页面参数会丢失)解决方法:在route.js中增加参数名
{path: '/intergral/addresslist/:id', component: AddressList, meta: {title: '收货地址',}}
2、vue组件通信有哪几种
1.父传子
父组件中传递:
<sec-kill :objDetails="objDetails"></sec-kill>
子组件中通过props接收:
props: {
//商品或者课程详情
objDetails: {
type: Object,
default: function () {
return {}
}
}
}
2.子传父
子组件中用thi.$emit()触发一个方法
//关闭弹窗
closeDown() {
//第一个参数为触发的方法名
//第二个为要传递的参数
this.$emit('hideDownload',false)
}
父组件中监听这个方法
<!-- 子组件触发的什么方法父组件就用@监听 -->
<downApp @hideDownload='hideDownload'></downApp>
methods: {
// 判断下载APP是否显示 msg: true 显示 false不显示
hideDownload(msg){
msg?this.addSize=true:this.addSize=false
}
}
3.兄弟组件
通过一个bus.js的js文件
js文件内容:
import Vue from 'vue'
//定义空的vue实例,作为实现非父子组件之间的通信
var goBackEntity = new Vue({});
export default goBackEntity;
使用方法:
1.在需要的页面引入bus.js 我这里叫whitePage.js随便什么都行
2.这里我理解为跟子组件往父组件传值类似 fromRelease为要触发的方法名 第二个参数是要传递的参数
eventBus.$emit('fromRelease',true);
3.然后就是接收的问题了,在需要接收的文件中同样引入这个bus.js紧接着使用:
eventBus.$on('fromRelease', (e) => {
//这个e就是传递过来的那个true
console.log(e)
})
3、什么是 mvvm?
MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。
在 MVVM 架构下,View 和 Model 之间并没有直接的联系,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互是双向的, 因此 View 数据的变化会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作 DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
4、mvvm 和 mvc 区别?
mvc 和 mvvm 其实区别并不大。都是一种设计思想。主要就是 mvc 中 Controller 演变成 mvvm 中的 viewModel。mvvm 主要解决了 mvc 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到 View 。
5、vue 的优点是什么?
- 低耦合。视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候 View 也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 view 重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用 Expression Blend 可以很容易设计界面并生成 xml 代码。
- 可测试。界面素来是比较难于测试的,而现在测试可以针对 ViewModel 来写。
6、vue生命周期的理解?
总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
- 创建前/后: 在 beforeCreate 阶段,vue 实例的挂载元素 el 还没有。
- 载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。
- 更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
- 销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在
7、active-class 是哪个组件的属性
参考文献:active-class的用法
vue-router 模块的 router-link 组件。
8、嵌套路由怎么定义?
在实际项目中我们会碰到多层嵌套的组件组合而成,但是我们如何实现嵌套路由呢?因此我们需要在 VueRouter 的参数中使用 children 配置,这样就可以很好的实现路由嵌套。
index.html,只有一个路由出口
<div id="app">
<!-- router-view 路由出口, 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
main.js,路由的重定向,就会在页面一加载的时候,就会将 home 组件显示出来,因为重定向指向了 home 组件,redirect 的指向与 path 的必须一致。children 里面是子路由,当然子路由里面还可以继续嵌套子路由。
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//引入两个组件
import home from "./home.vue"
import game from "./game.vue"
//定义路由
const routes = [
{ path: "/", redirect: "/home" },//重定向,指向了home组件
{
path: "/home", component: home,
children: [
{ path: "/home/game", component: game }
]
}
]
//创建路由实例
const router = new VueRouter({routes})
new Vue({
el: '#app',
data: {
},
methods: {
},
router
})
home.vue,点击显示就会将子路由显示在出来,子路由的出口必须在父路由里面,否则子路由无法显示。
9、路由之间跳转?
声明式(标签跳转)
编程式( js 跳转) router.push(‘index’)
10、懒加载(按需加载路由)?
webpack 中提供了 require.ensure()来实现按需加载。以前引入路由是通过 import 这样的方式引入,改为 const 定义的方式进行引入。
- 不进行页面按需加载引入方式:
import home from '../../common/home.vue'
- 进行页面按需加载的引入方式:
const home = r => require.ensure( [], () => r (require('../../common/home.vue')))
11、vuex 是什么?怎么使用?哪种功能场景使用它?
vue 框架中状态管理。在 main.js 引入 store,注入。新建了一个目录 store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
// 新建 store.js
import vue from 'vue'
import vuex form 'vuex'
vue.use(vuex)
export default new vuex.store({
//...code
})
//main.js
import store from './store'
...
12、vue-router 有哪几种导航钩子?
-
全局导航钩子
router.beforeEach(to, from, next)
router.beforeResolve(to, from, next)
router.afterEach(to, from ,next) -
组件内钩子
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave -
单独路由独享组件
beforeEnter
13、自定义指令(v-check, v-focus) 的方法有哪些? 它有哪些钩子函数? 还有哪些钩子函数参数?
- 全局定义指令:在 vue 对象的 directive 方法里面有两个参数, 一个是指令名称, 另一个是函数。
- 组件内定义指令:directives(vue中directives的用法)
- 钩子函数: bind(绑定事件出发)、inserted(节点插入时候触发)、update(组件内相关更新)
- 钩子函数参数: el、binding
14、说出至少 4 种 vue 当中的指令和它的用法
v-if(判断是否隐藏)、v-for(把数据遍历出来)、v-bind(绑定属性)、v-model(实现双向绑定)
15、vue 的双向绑定的原理是什么
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter 这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化
第二步:compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:
-
在自身实例化时往属性订阅器(dep)里面添加自己
-
自身必须有一个 update()方法
-
待属性变动 dep.notice()通知时,能调用自身的 update() 方法,并触发 Compile 中绑定的回调,则功成身退。
第四步:MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。
16、vuex 有哪几种属性
有 5 种,分别是 state、getter、mutation、action、module
17、vuex 的 store 特性是什么
-
vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 data
-
state 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新
-
它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性
18、vuex 的 getter 特性是什么
-
getter 可以对 state 进行计算操作,它就是 store 的计算属性
-
虽然在组件内也可以做计算属性,但是 getters 可以在多给件之间复用
-
如果一个状态只在一个组件内使用,是可以不用 getters
19、vuex 的 mutation 特性是什么
-
action 类似于 muation, 不同在于:action 提交的是 mutation,而不是直接变更状态
-
action 可以包含任意异步操作
20、vue 中 ajax 请求代码应该写在组件的 methods 中还是 vuex 的 action 中
-
如果请求来的数据不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入 vuex 的 state 里
-
如果被其他地方复用,请将请求放入 action 里,方便复用,并包装成 promise 返回
21、vuex 原理
-
vuex 仅仅是作为 vue 的一个插件而存在,不像 Redux,MobX 等库可以应用于所有框架,vuex 只能使用在 vue 上,很大的程度是因为其高度依赖于 vue 的 computed 依赖检测系统以及其插件系统,
-
vuex 整体思想诞生于 flux,可其的实现方式完完全全的使用了 vue 自身的响应式设计,依赖监听、依赖收集都属于 vue 对对象 Property set get 方法的代理劫持。最后一句话结束 vuex 工作原理,vuex 中的 store 本质就是没有 template 的隐藏着的 vue 组件;
22、使用 Vuex 只需执行 Vue.use(Vuex),并在 Vue 的配置中传入一个 store 对象的示例,store 是如何实现注入的?
Vue.use(Vuex) 方法执行的是 install 方法,它实现了 Vue 实例对象的 init 方法封装和注入,使传入的 store 对象被设置到 Vue 上下文环境的store中。因此在VueComponent任意地方都能够通过this.store 访问到该 store。
23、state 内部支持模块配置和模块嵌套,如何实现的?
在 store 构造方法中有 makeLocalContext 方法,所有 module 都会有一个 local context,根据配置时的 path 进行匹配。所以执行如 dispatch(‘submitOrder’, payload)这类 action 时,默认的拿到都是 module 的 local state,如果要访问最外层或者是其他 module 的 state,只能从 rootState 按照 path 路径逐步进行访问。
24、在执行 dispatch 触发 action(commit 同理)的时候,只需传入(type, payload),action 执行函数中第一个参数 store 从哪里获取的?
store 初始化时,所有配置的 action 和 mutation 以及 getters 均被封装过。在执行如 dispatch(‘submitOrder’, payload)的时候,actions 中 type 为 submitOrder 的所有处理方法都是被封装后的,其第一个参数为当前的 store 对象,所以能够获取到 { dispatch, commit, state, rootState } 等数据。
25、Vuex 如何区分 state 是外部直接修改,还是通过 mutation 方法修改的?
Vuex 中修改 state 的唯一渠道就是执行 commit(‘xx’, payload) 方法,其底层通过执行 this._withCommit(fn) 设置_committing 标志变量为 true,然后才能修改 state,修改完毕还需要还原_committing 变量。外部修改虽然能够直接修改 state,但是并没有修改_committing 标志位,所以只要 watch 一下 state,state change 时判断是否_committing 值为 true,即可判断修改的合法性。
26、调试时的"时空穿梭"功能是如何实现的?
devtoolPlugin 中提供了此功能。因为 dev 模式下所有的 state change 都会被记录下来,‘时空穿梭’ 功能其实就是将当前的 state 替换为记录中某个时刻的 state 状态,利用 store.replaceState(targetState) 方法将执行 this._vm.state = state 实现。
27、axios 是什么?怎么使用?描述使用它实现登录功能的流程
axios 是请求后台资源的模块。 npm i axios -S
如果发送的是跨域请求,需在配置文件中 config/index.js 进行配置
28、不用 vuex 会带来什么问题
-
可维护性会下降,你要修改数据,你得维护 3 个地方
-
可读性下降,因为一个组件里的数据,你根本就看不出来是从哪里来的
-
增加耦合,大量的上传派发,会让耦合性大大的增加,本来 Vue 用 Component 就是为了减少耦合,现在这么用,和组件化的初衷相背