MVC:
MVC是应用最广泛的软件架构之一,一般MVC
分为:
Model( 模型 )
、Controller( 控制器 )
、View( 视图 )
。
这主要是基于分层的目的,让彼此的职责分开。View
一般通过 Controller
来和 Model
进行联系。Controller
是 Model
和 View
的协调者,View
和Model
不直接联系。基本联系都是单向的。
1、View 传送指令到 Controller
2、Controller 完成业务逻辑后,要求 Model 改变状态
3、Model 将新的数据发送到 View,用户得到反馈
MVP:
MVP 模式将 Controller 改名为 Presenter
,同时改变了通信方向。
1、各部分之间的通信,都是双向的。
2、View 与 Model 不发生联系,都通过 Presenter 传递。
3、View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
MVVM
MVVM
是把 MVC
的 Controller
和 MVP
的 Presenter
改成了 ViewModel
。
View
的变化会自动更新到 ViewModel
,ViewModel
的变化也会自动同步到 View
上显示。这种自动同步是因为 ViewModel
中的属性实现了 Observer
,当属性变更时都能触发对应的操作。
MVVM模式的优点:
1、低耦合:
视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2、可重用性:
你可以把一些视图逻辑放在一个ViewModel里面,让很多 view 重用这段视图逻辑。
3、独立开发:
开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
4、可测试:
界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
MVVM 和 MVC 的区别:
mvc
和 mvvm
其实区别并不大。都是一种设计思想。
主要区别
mvc 中 Controller演变成 mvvm 中的 viewModel,
mvvm 通过数据来显示视图层而不是节点操作。
mvvm主要解决了: mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
实现数据绑定的做法有大致如下几种:
发布者-订阅者模式(backbone.js)
脏值检查(angular.js)
数据劫持(vue.js)
1、发布者-订阅者模式:
一般通过sub
, pub
的方式实现数据和视图的绑定监听,
更新数据方式通常做法是 vm.set('property', value)
。
这种方式现在毕竟太low了,我们更希望通过 vm.property = value
这种方式更新数据,同时自动更新视图,于是有了下面两种方式。
2、脏值检查:
angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,
最简单的方式就是通过 setInterval() 定时轮询检测数据变动,
angular只有在指定的事件触发时进入脏值检测,大致如下:
1、DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
2、XHR响应事件 ( $http )
3、浏览器Location变更事件 ( $location )
4、Timer事件( $timeout , $interval )
5、执行 $digest() 或 $apply()
3、数据劫持:
vue.js 则是采用数据劫持
结合发布者-订阅者
模式的方式,
通过Object.defineProperty()
来劫持各个属性的setter
,getter
,
在数据变动时发布消息给订阅者,触发相应的监听回调。
Object.defineProperty() 方法
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
语法:
Object.defineProperty(obj, prop, descriptor)
参数说明:
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
返回值:
传入函数的对象。即第一个参数obj
针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for…in或Object.keys()遍历。
给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。
1、数据驱动,也叫双向数据绑定。
Vue.js数据观测原理在技术实现上,利用的是ES5Object.defineProperty和存储器属性: getter和setter(所以只兼容IE9及以上版本),可称为基于依赖收集的观测机制。核心是VM,即ViewModel,保证数据和视图的一致性。
2、组件系统。
.vue组件的核心选项:
1、模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
2、初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。
3、接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。
4、方法(methods):对数据的改动操作一般都在组件的方法内进行。
5、生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。
6、私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。
等等。
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情…
当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿
当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom
经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等,组件的数据绑定、监听…去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以
如果觉得上面的太长,也可以如下回答:
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素el还没有。在created阶段,vue实例的数据对象data有了,el还没有.
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
生命周期中有多个事件钩子,让我们在控制整个 vue 实例的过程时更容易形成好的逻辑
第一次加载会触发 beforeCreate、created、beforeMount、mounted
生命周期钩子的一些使用方法:
beforecreate : 可以在这加个loading事件,在加载实例时触发
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
看实际情况,一般在 created(或beforeRouter) 里面就可以,如果涉及到需要页面加载完成之后的话就用 mounted。
在created的时候,视图中的html并没有渲染出来,所以此时如果直接去操作html的dom节点,一定找不到相关的元素
而在mounted中,由于此时html已经渲染出来了,所以可以直接操作dom节点,(此时document.getelementById 即可生效了)
“Vue路由就是指vue-router,其中router是指根据url分配到对应的处理程序,所以说路由就是用来解析URL以及调用对应的控制器并返回从视图对象中提取好的网页代码给web服务器,最终返回给客户端。
优点:
缺点:
Vue的路由实现:hash模式 和 history模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
特点:
定义动态路由:
获取动态路由传过来的值:
params.id
获取//全局获取动态路由传递过来的值
$route.params.id
//局部或者是在方法内获取
this.$route.params.id
vue-router 的导航钩子,主要用来作用是拦截导航,让他完成跳转或取消。
全局的
单个路由独享的
组件级的
vue-router全局有三个守卫:
组件内的守卫:
to,from,next 这三个参数:
我们可以这样跳转:next(‘path地址’)或者next({path:’’})或者next({name:’’})
且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及你用在router-link或router.push的对象选项。
三种:
接收:
query使用path和name传参跳转都可以,而params只能使用name传参跳转。
传参跳转页面时,query不需要再路由上配参数就能在新的页面获取到参数,params也可以不用配,但是params不在路由配参数的话,当用户刷新当前页面的时候,参数就会消失。
也就是说使用params不在路由配参数跳转,只有第一次进入页面参数有效,刷新页面参数就会消失。
异步组件
和 Webpack 的代码分割
功能,轻松实现路由组件的懒加载。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
我的个人理解是vuex其实就是一个管理数据的工具,通过vuex我们可以解决组件之间数据共享的问题,后期也方便我们管理以及维护
优点:
缺点:
每个Vuex应用的本质是store(仓库),包含应用中大部分的状态。
state, getters,mutations,actions,module
安装vuex
在src目录下创建store文件夹,在该文件夹内创建index.js
在store文件夹内的index.js文件内引入vuex
然后在引入vue
调用Vue.use()方法注册vuex
对vuex进行实例化
进行实例化之后通过export default导出
在main.js文件内引入store文件夹内的index.js文件
挂载到new Vue实例上面
初始化vuex的状态和属性
在vue组件里面,通过dispatch来触发actions提交修改数据的操作。
然后再通过actions的commit来触发mutations来修改数据。
mutations接收到commit的请求,就会自动通过Mutate来修改state(数据中心里面的数据状态)里面的数据。
最后由store触发每一个调用它的组件的更新
actions去异步的改变state的状态,mutations是同步改变状态,调用actions内定义的方法,需要通过this. s t o r e . d i s p a t c h ( ) , m u t a t i o n s 方 法 是 通 过 t h i s . store.dispatch(),mutations方法是通过this. store.dispatch(),mutations方法是通过this.store.commit()来进行调用,而在actions要调用mutations的方法,通过commit来进行调用
localStorage 或者就是sessionStorage ,或者借用辅助插vuex-persistedstate
通过$watch监听mutation的commit函数中_committing是否为true
vue组件的通信是为了解决组件之间数据传递的问题,分为
父子组件之间的通信
非父子组件的通信
$emit
向父组件触发一个事件,父组件监听这个事件就行了 路由,vuex,本地存储
v-if
和 v-show
都是动态显示DOM元素。编译过程:
v-if 是 真正 的 条件渲染,因为它会确保在切换过程中条件块内的事件监听器
和子组件
适当地被销毁
和重建
。v-show
的元素始终会
被渲染并保留在 DOM 中
。v-show
只是简单地切换
元素的 CSS 属性display
。编译条件:
v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做。直到条件第一次变为真时,才会开始渲染条件块。v-show
不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换v-if有更高的切换消耗。v-show有更高的
初始渲染消耗`。应用场景:
v-if适合运行时条件很少改变时使用。v-show适合频繁切换keep-alive:
主要用于保留组件状态
或避免重新渲染
。列表页面
和一个 详情页面
,那么用户就会经常执行打开详情=>返回列表=>打开详情
这样的话 列表 和 详情 都是一个频率很高
的页面,那么就可以对列表组件
使用``进行缓存,这样用户每次返回列表
的时候,都能从缓存中快速渲染
,而不是重新渲染
ref
`v-bind,v-if,v-show,v-model等等
Vue
会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做使 Vue 变得非常快,但是这样也不总是符合实际需求。什么是axios?
axios一般什么时候用?
使用场景?
使用的时候遇到过什么问题?
vue使用反向代理
computed是计算属性,有缓存性,当属性发生变化的时候才会执行,watch是监听,没有缓存,依赖于data,当data发生变化的时候才会执行,methods是方法,没有缓存,只要调用就会执行
`
就是主张最少,可以只用一部分功能,而不必使用全部,而且可以跟其他框架结合使用,
没有多做职责之外的事
你可以在一个组件的选项中定义本地的过滤器:
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
或者在创建 Vue 实例之前全局定义过滤器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
自定义指令:使用Vue.directive(id,definition)注册全局自定义指令,使用组件的directives选项注册局部自定义指令。
钩子函数:
bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
update:第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值,之后被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
unbind:只调用一次, 指令与元素解绑时调用。
钩子函数的参数:(el, binding, vnode, oldVnode)
jquery是直接操作DOM的而vue是操作数据的
vue做到了数据和视图完全分离,他首先把值和JS对象进行绑定,然后在修改JS对象的值,vue框架就会自动把DOM的值进行更新,对数据进行操作不在需要引用相应的DOM对象,他们通过Vue对象实现数据和视图的相互绑定
jquery则是先使用选择器($)来选取Dom对象,然后对Dom对象进行操作(如赋值丶取值丶事件绑定等)
打包后文件无法读取
在config.js中设置module.exports = {
publicPath: ‘./’,
}
1、react严格上针对的是mvc模式的view层,vue则是mvvm模式。
2、操作dom的方式不同,vue使用的是指令操作dom,react是通过js进行操作。
3、数据绑定不同,vue实现的是双向绑定,react的数据流动是单向的。
4、react中state是不能直接改变的,需要使用setState改变。vue中的state不是必须的,数据主要是由data属性在vue对象中管理的。
图片懒加载,路由懒加载等等
插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制
就是将重复使用的代码放在组件中,通过传参或插槽的形式实现复用
模拟数据进行功能的编写
就是将重复使用的代码放在组件中,通过传参或插槽的形式实现复用
element-ui vant
.stop,.once,.prevent等等
ajax是原生的异步方法,axios是封装后的方法,比ajax更加简便,同时可以避免地狱回掉问题
rem,vw\vh
正常的CSS中的方法
input:disabled{
color:xxx;
opacity:1;
//text-fill-color文本填充颜色,只兼容webkit内核
-webkit-text-fill-color:xxx;
-webkit-opacity:1;
font-size:16px;
}
使用v-model来实现
Vue 实现 双向数据绑定 主要采用:数据劫持结合“发布-订阅”模式的方式,通过Object.defineProperty()的 set 和 get,在数据变动时发布消息给订阅者触发监听。
当客户端向服务器发送数据的时候就是请求,当服务器向客户端发送数据就是响应,那么请求拦截和响应拦截分别是在发送数据前进行拦截还有是在接受数据没有渲染到页面时候进行拦截,拦截点2个。