前端面试题七@杨志刚

对mvc、mvvm、mvp的理解

mvc

Models: 数据层,负责数据的请求和存储以及处理

View: 展示层,负责View和动画效果的展示,以及用户的交互

Controller: 控制器层,负则连接View和Model,对view的交互事件有controller层处理传递给model,model处理再交互传递给Controller,Controller传递给view

M和View应该是完全隔离的,由C作为中间人来负责二者的交互,同时三者是完全独立分开的,这样可以保证M和V的可测试性和复用性,但是一般由于C都是为特别的应用场景下的M和V做中介者,所以很难复用。

优点

增强代码复用性耦合性低: V对外只暴露Set方法,对M甚至C都是个例状态,复用没问题

解决代码臃肿: 布局转移到了View层,业务逻辑转移到了Model层

易拓展:无论产品想增加或者模块,只需增加响应的MVC模块

可维护:各个模块相互隔离,哪里出错改哪里,不影响其他模块。

缺点

简单的小型项目,使用MVC设计反而会降低开发效率层和层虽然相互分离,但是之间关联性太强,没有做到独立的重用。

对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率

视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

mvvm

MVVM其实是在MVP的基础上发展起来的。那么MVVM在MVP的基础上改良了啥呢?答案就是数据绑定。从 Model-View-ViewModel 这个名字来看,它由三个部分组成,也就是 Model、View 和 ViewModel;其中视图模型(ViewModel)其实就是 MVP 模式中的P,在 MVVM 中叫做VM。

除了我们非常熟悉的 Model、View 和 ViewModel 这三个部分,在 MVVM 的实现中,还引入了隐式的一个 Binder层,这也是MVVM相对MVP的进步,而声明式的数据和命令的绑定在 MVVM 模式中就是通过binder层来完成的,RAC是iOS下binder的优雅实现,当然MVVM没有RAC也完全可以运行。

缺点

View和Viewmodel因为双向绑定所以没有复用性。

mvp

VC层:

生成的View添加到self.view上面

管理View的声明周期

通过P层去获取数据然后渲染到View上面展示。

Controller层:

生成view,实现view的代理和数据源

绑定view和presenter

调用presenter执行业务逻辑

负责界面跳转

View层:

监听P层数据更新通知,刷新页面展示

点击事件触发时调用P层响应的方法

界面元素搭建,动画展示

接受用户操作并提供反馈

Model层:

与MVC的model层一样

Persneter层:

实现view的事件处理逻辑,暴露相应的接口给view的事件调用

调用model的接口获取数据,然后加工数据,封装成view可以直接用来显示的数据和状态

这里又有两种不同的实现方式:

让P持有V,P通过V的暴露接口改变V的显示数据和状态,P通过V的事件回调来执行自身的业务逻辑

让V持有P,V通过P的代理回调来改变自身的显示数据和状态,V直接调用P的接口来执行事件响应对应的业务逻辑

第一种方式保持了view的纯粹,只是作为被动view来展示数据和更改状态,但是却导致了P耦合了V,这样业务逻辑和业务展示有糅合到了一起,和上面的MVC一样了。

第二种方式保证了P的纯粹,让P只做业务逻辑,至于业务逻辑引发的数据显示的变化,让view实现对应的代理事件来实现即可。这增加了view的复杂和view对于P的耦合。

MVP相对于MVC, 它其实只做了一件事情, 即分割业务展示和业务逻辑. 展示和逻辑分开后, 只要我们能保证V在收到P的数据更新通知后能正常刷新页面, 那么整个业务就没有问题. 因为V收到的通知其实都是来自于P层的数据获取/更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了. 即我们只用测试P层的逻辑, 不必关心V层的情况

对$nexttick的理解及使用场景

vue是依靠数据驱动视图更新的,该更新的过程是异步的。即:当侦听到你的数据发生变化时, Vue将开启一个队列(该队列被Vue官方称为异步更新队列)。视图需要等队列中所有数据变化完成之后,再统一进行更新。

Vue 实现的响应式并不是数据发生变化之后视图立即变化。

我们可以通过$nextTick() 获取到更新之后的DOM。

因为 $nextTick() 返回一个 Promise 对象,所以我们也可以使用async/await语法完成相同的事情

应用场景

1、如果要在created()钩子函数中进行的DOM操作,由于created()钩子函数中还未对DOM进行任何渲染,所以无法直接操作,需要通过$nextTick()来完成。

2、更新数据后,想要使用js对新的视图进行操作时。

3、在使用某些第三方插件时 ,这些插件需要dom动态变化后重新应用该插件,这时候就需要使用$nextTick()来重新应用插件的方法。

对渐进式框架的理解

渐进式框架的大概意思就是你可以只用我的一部分,而不是用了我这一点就必须用我的所有部分。

Vue的核心的功能,是一个视图模板引擎,但这不是说Vue就不能成为一个框架。我们可以通过添加组件系统、客户端路由、大规模状态管理来构建一个完整的框架。更重要的是,这些功能相互独立,你可以在核心功能的基础上任意选用其他的部件,不一定要全部整合在一起。可以看到,所说的“渐进式”,其实就是Vue的使用方式,同时也体现了Vue的设计的理念

渐进式代表的含义是:主张最少。

每个框架都不可避免会有自己的一些特点,从而会对使用者有一定的要求,这些要求就是主张,主张有强有弱,它的强势程度会影响在业务开发中的使用方式。

比如说,Angular,它两个版本都是强主张的,如果你用它,必须接受以下东西:

- 必须使用它的模块机制- 必须使用它的依赖注入- 必须使用它的特殊形式定义组件(这一点每个视图框架都有,难以避免)

所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西集成,这些主张会带来一些困扰。

比如React,它也有一定程度的主张,它的主张主要是函数式编程的理念,比如说,你需要知道什么是副作用,什么是纯函数,如何隔离副作用。它的侵入性看似没有Angular那么强,主要因为它是软性侵入。

Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一两个组件改用它实现,当jQuery用;也可以整个用它全家桶开发,当Angular用;还可以用它的视图,搭配你自己设计的整个下层用。你可以在底层数据逻辑的地方用OO和设计模式的那套理念,也可以函数式,都可以,它只是个轻量视图而已,只做了自己该做的事,没有做不该做的事,仅此而已。

渐进式的含义,我的理解是:没有多做职责之外的事。

组件样式属性scoped问题及解决方法

在父组件中无法修改子组件样式问题

一、混合使用全局属性和局部属性

二、关于子组件的根元素

  使用了scoped属性之后,父组件的style样式将不会渗透到子组件中,然而子组件的根节点元素会同时被设置了scoped的父css样式和设置了scoped的子css样式影响,这么设计的目的是父组件可以对子组件根元素进行布局。 

  .vue模板中的样式是根据需要按需加载,访问一个页面该组件中的样式就会追加到head标签中,如果父子组件中都对某个子组件根节点元素进行了控制,则父组件里的样式会被后来的覆盖。

三、深选择器

  如果想对设置了scoped的子组件里的元素进行控制可以使用  ’>>>’  或者  ’deep’

四、动态生成的内容

  使用v-html动态创建的DOM内容,不受设置scoped的样式影响,但你依然可以使用深选择器进行控制

你可能感兴趣的:(前端面试题七@杨志刚)