1、提到框架,先引入框架模式MVC、MVVM、MVP,下面分别介绍了其概念及异同css
MVC是Model-View-Controller的缩写,特色在于实现关注点分离,即应用程序中的数据模型与业务和展现逻辑解耦。它将应用程序划分为三个部分:html
Model: 模型(用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法)View: 视图(渲染页面)Controller: 控制器(M和V之间的链接器,用于控制应用程序的流程,及页面的业务逻辑)前端
MVC流程一共有两种:vue
一种是经过 View 接受指令,传递给 Controller,而后对模型进行修改或者查找底层数据,最后把改动渲染在视图上。 另外一种是经过controller接受指令,传给View。node
MVP是MVC改良模式,和MVC的相同之处在于:Controller/Presenter负责业务逻辑,Model管理数据,View负责显示只不过是将 Controller 更名为 Presenter,同时改变了通讯方向。react
M、V、P之间双向通讯。View 与 Model 不通讯,都经过 Presenter 传递。Presenter彻底把Model和View进行了分离。webpack
MVVM是Model-View-ViewModel的简写,主要目的是分离视图(View)和模型(Model)。 git
MVVM特色: 1) 低耦合。视图(View)能够独立于Model变化和修改,一个ViewModel能够绑定到不一样的"View"上,当View变化的时候Model能够不变,当Model变化的时候View也能够不变。angularjs
2.)可重用性。你能够把一些视图逻辑放在一个ViewModel里面,让不少view重用这段视图逻辑。es6
3)独立开发。开发人员能够专一于业务逻辑和数据的开发(ViewModel),设计人员能够专一于页面设计。
4)可测试。界面素来是比较难于测试的,而如今测试能够针对ViewModel来写。
MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通讯是经过 Presenter (MVC中的Controller)来进行的,全部的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是经过 Controller。
MVVM 模式将 Presenter 更名为 ViewModel,基本上与 MVP 模式彻底一致。 惟一的区别是,它采用双向绑定(data-binding):View的变更,自动反映在 ViewModel,反之亦然。这样开发者就不用处理接收事件和View更新的工做,框架已经帮你作好了。
2、Vue.js 是什么
Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有很是容易上手的API;
Vue.js是一个构建数据驱动的Web界面的库。
Vue.js是一套构建用户界面的渐进式框架。与其余重量级框架不一样的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,而且很是容易学习,很是容易与其它库或已有项目整合。另外一方面,Vue 彻底有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用。数据驱动+组件化的前端开发。
简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进式框架。Vue.js 的目标是经过尽量简单的 API 实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。
什么是数据驱动
数据驱动是vue.js最大的特色。在vue.js中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不须要手动的去修改dom。
vue专一于ViewModel层,view对应DOM,Model对应js对象。vue经过Directives指令操做view,对dom监听,经过dom listener改变model层变化。最终实现双向绑定。
那么vuejs是如何实现这种数据驱动的呢?(双向绑定)
首先,vuejs在实例化的过程当中,会对实例化对象选项中的data 选项进行遍历,遍历其全部属性并使用 Object.defineProperty 把这些属性所有转为 getter/setter。同时每个实例对象都有一个watcher实例对象,他会在模板编译的过程当中,用getter去访问data的属性,watcher此时就会把用到的data属性记为依赖,这样就创建了视图与数据之间的联系。当以后咱们渲染视图的数据依赖发生改变(即数据的setter被调用)的时候,watcher会对比先后两个的数值是否发生变化,而后肯定是否通知视图进行从新渲染这样就实现了所谓的数据对于视图的驱动。
Vue.js的特性以下:
1.轻量级的框架
2.双向数据绑定
3.指令
4.插件化
渐进式的理解:
Vue的核心的功能,是一个视图模板引擎,但这不是说Vue就不能成为一个框架。以下图所示,这里包含了Vue的全部部件,在声明式渲染(视图模板引擎)的基础上,咱们能够经过添加组件系统、客户端路由、大规模状态管理来构建一个完整的框架。更重要的是,这些功能相互独立,你能够在核心功能的基础上任意选用其余的部件,不必定要所有整合在一块儿。能够看到,所说的“渐进式”,其实就是Vue的使用方式,同时也体现了Vue的设计的理念
图挂了,见https://blog.csdn.net/weixin_41049850/article/details/79431682
好比,Angular,它两个版本都是强主张的,若是你用它,必须接受如下东西:
因此Angular是带有比较强的排它性的,若是你的应用不是从头开始,而是要不断考虑是否跟其余东西集成,这些主张会带来一些困扰。
好比React,它也有必定程度的主张,它的主张主要是函数式编程的理念,好比说,你须要知道什么是反作用,什么是纯函数,如何隔离反作用。它的侵入性看似没有Angular那么强,主要由于它是软性侵入。
Vue是渐进的,没有强主张,你能够在原有大系统的上面,把一两个组件改用它实现,当jQuery用。
三.Vue.js与其余框架的区别?
1.与angularjs的区别
相同点:
都支持指令:内置指令和自定义指令。都支持过滤器:内置过滤器和自定义过滤器。都支持双向数据绑定。都不支持低端浏览器。
不一样点:
(1).AngularJS的学习成本高,好比增长了Dependency Injection特性,而Vue.js自己提供的API都比较简单、直观。(2).在性能上,AngularJS依赖对数据作脏检查,因此Watcher越多越慢。Vue.js使用基于依赖追踪的观察而且使用异步队列更新。全部的数据都是独立触发的。对于庞大的应用来讲,这个优化差别仍是比较明显的。
脏检查:
在 angular中,他没有办法判断你的数据是否作了更改, 因此它设置了一些条件,当你触发了这些条件以后,它就执行一个检测来遍历全部的数据,对比你更改了地方,而后执行变化。这个检查很不科学。并且效率不高,有不少多余的地方,因此官方称为 脏检查
2.与React的区别
相同点:
react采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,二者都须要编译后使用。
中心思想相同:一切都是组件,组件实例之间能够嵌套。都提供合理的钩子函数,可让开发者定制化地去处理需求。都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载。在组件开发中都支持mixins的特性。
不一样点:
React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果作脏检查。Vue.js在模板中提供了指令,过滤器等,能够很是方便,快捷地操做DOM。
3.吸收两家之长,借鉴了Angular的指令(v-show,v-hide)和React的组件化(优势:可维护性,复用性)
4、vue核心内容:
一、vue-cli:
vue是以组件化开发的,最好要搭配webpack构建工具开发,独立搭建对大部分人较为困难,vue-cli就能很好解决这一问题。即便你对webpack还不是很了解,你也能够先搭建好项目在慢慢研究。cli已经将须要的东西配置好,只要写好项目业务,在用命令行就能够达到调试或打包的功能。
安装:
首先node版本最好高于4.x.x,稳定。而后执行npm install -g vue-cli,安装后选择webpack模板(也可选择其余模板)vue init webpack 项目名称而后按照提示选择一些选项,以后按照后面提示执行cd 项目名称,npm install便可。项目可经过npm run dev创建服务器,监听了8080端口,就能够经过localhost:8080访问了。
各文件功能:
项目名称 ->build ------------------------------------------ webpack配置相关文件 ->config ------------------------------------------ webpack配置相关文件 ->node_modules ------------------------------------------ 依赖代码库 ->src ------------------------------------------ 存放源码 ->static ------------------------------------------ 存放第三方静态资源 ->.babelrc.JSON ------------------------------------------ babe的配制,用于从es6编译至es5 ->.editorconfig ------------------------------------------ 编译器配置 ->.eslintignore ------------------------------------------ 忽略语法检查的目录文件 ->.eslintrc.js ------------------------------------------ eslint的配置 ->.gitignore ------------------------------------------ git忽略的目录或文件 ->index.html ------------------------------------------ 入口文件,项目编译过程当中会自动插入其中 ->package.json ------------------------------------------ 配置文件,描述一个项目 ->README.md ------------------------------------------ 项目描述文件
2.webpack
找到JS模块及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
Webpack的工做方式是:把你的项目当作一个总体,经过一个给定的主文件(如:index.js),使用entry 属性来定义入口。Webpack将从这个文件开始找到你的项目的全部依赖文件,使用loaders处理它们,最后打包为一个或多个浏览器可识别的JavaScript文件。
出口:webpack 的 output 属性描述了如何处理归拢在一块儿的代码。
module.exports: 在咱们本身写模块的时候,须要在模块最后写好模块接口,声明这个模块对外暴露什么内容,module.exports 提供了暴露接口的方法
插件在 webpack 的配置信息 plugins 中指定,用于完成一些 loader 不能完成的工做。好比咱们能够安装内置的 BannerPlugin 插件,用于在文件头部输出一些注释信息
Babel是一个编译JSt的平台,能使用最新的JavaScript代码(ES6,ES7...),能使用基于JavaScript进行了拓展的语言,好比React的JSX。
Loader:webpack只能处理JS模块,若是要处理其余类型的文件,就须要使用 loader 进行转换。css-loader 和 style-loader,两者处理的任务不一样, css-loader使你可以使用相似@import
和 url(...)
的方法实现 require()
的功能,style-loader将全部的计算后的样式加入页面中,两者组合在一块儿使你可以把样式表嵌入webpack打包后的JS文件中。
3.v-if和v-show
v-if是动态的向DOM树内添加或者删除DOM元素; 适合运营条件不大可能改变;切换有一个局部编译/卸载的过程,切换过程当中合适地销毁和重建内部的事件监听和子组件;
v-show是经过设置DOM元素的display样式属性控制显隐;适合频繁切换;只是简单的基于css切换。
v-else元素必须跟在前面二者之一的后面,不然不能被识别。
4.v-bind
用于响应地更新 HTML 特性 形式如:v-bind:href 缩写为 :href;
5.v-on
用于监听DOM事件 形式如:v-on:click 缩写为 @click;
Vue.js 为v-on提供了事件修饰符。在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是很是常见的需求。尽管咱们能够在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
<!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件再也不重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符能够串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即元素自身触发的事件先在此到处理,而后才交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div> 使用修饰符时,顺序很重要;相应的代码会以一样的顺序产生。所以,用 v-on:click.prevent.self 会阻止全部的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
6.Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,也就是 Vuex 就是处理数据的。
store是Vuex应用的核心,基本上就是一个容器,它包含着你的应用中大部分的状态(state)。
Vuex如何管理数据:
state:惟一数据源 打个比方:state中定义一个x值,在整个应用中任意地方均可以取到。
getters: 就是计算属性。
mutations: 更改state的惟一方法(只能同步,异步处理放在action中)。每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler) ,事件类型 = 方法名,回调函数 = 方法
actions: 处理mutations不能作的异步操做。其中 分发 就是 触发
modules: 将前面四个分红modules = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } }
七、一些重要的全局API
Vue.extend():建立一个子类,参数是一个包含组件选项的对象。而后使用$mount挂载到元素上.
注:extend和component做用基本相同,区别仅在于当咱们不须要组件名称时,使用extend更简便些; 而当咱们须要使用新的标签时,那么请使用component去建立组件
var author = Vue.extend({ template: "<p><a :href='url'>{{author}}</a></p>", data : function() { return { author : 'vamous', url : 'http://blog.csdn.net/Dear_Mr/article/details/72614370' } } }); 对应的HTML:<author></author> 扩展实例构造器须要挂载:new author().$mount('author');
Vue.nextTick([callback,context]):修改数据后马上使用这个方法,获取更新后的DOM
// 修改数据 vm.msg = 'Hello' // DOM 尚未更新 Vue.nextTick(function () { // DOM 更新了 })
Vue.set(object,key,value):设置对象的属性。若是对象是响应式的,确保属性被建立后也是响应式的,同时触发视图更新。这个方法用于避开Vue不能检测属性被添加的限制。
Vue.delete(object,key):删除对象的属性。若是对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制,可是你应该不多会使用它。
Vue.directive(id,function(){}):注册指令,指令跟组件同样须要注册才能使用。提供了五个钩子函数来供咱们使用,分别表明了一个组件的各个生命周期。
>bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数能够定义一个在绑定时执行一次的初始化动做。
>inserted: 被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于 document 中)。
>update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。经过比较更新先后的绑定值,能够忽略没必要要的模板更新(详细的钩子函数参数见下)。
>componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
>unbind: 只调用一次, 指令与元素解绑时调用。
实例,刷新页面input自动获取焦点
<div id="app"> <input type="text" v-focus/> </div> <script> // 注册一个全局自定义指令 v-focus Vue.directive('focus', { // 当绑定元素插入到 DOM 中。 inserted: function (el,binding) { // 聚焦元素 el.focus(); } }); new Vue({ el:'#app' }); </script>
Vue.filter( id, [definition] ):注册或获取全局过滤器.
// 注册 Vue.filter('my-filter', function (value) { // 返回处理后的值 }) // getter,返回已注册的过滤器 var myFilter = Vue.filter('my-filter')
Vue.component(id, [definition]):注册或获取全局组件。注册还会自动使用给定的id
设置组件的名称
// 注册组件,传入一个扩展过的构造器 Vue.component('my-component', Vue.extend({ /* ... */ })) // 注册组件,传入一个选项对象(自动调用 Vue.extend) Vue.component('my-component', { /* ... */ }) // 获取注册的组件(始终返回构造器) var MyComponent = Vue.component('my-component')
Vue.mixin:混入 (mixins) 是一种分发 Vue 组件中可复用功能的很是灵活的方式。混入对象能够包含任意组件选项。当组件使用混入对象时,全部混入对象的选项将被混入该组件自己的选项。
通俗一点的说,就是定义一部分公共的方法或者计算属性,而后混入到各个组件中使用,方便管理与统一修改。
// 定义一个混入对象 var myMixin = { created: function () { this.hello() }, methods: { hello: function () { console.log('hello from mixin!') } } } // 定义一个使用混入对象的组件 var Component = Vue.extend({ mixins: [myMixin] }) var component = new Component() // => "hello from mixin!"
八、props:能够是数组或对象,用于接收来自父组件的数据。
九、watch:键是须要观察的表达式,值是对应回调函数。Vue实例将会在实例化时调用之,遍历watch对象的每个属性。
十、render:字符串模板的代替方案,容许你发挥 JavaScript 最大的编程能力。
十一、生命周期钩子
beforecreated:el 和 data 并未初始化 ,能够在这加个loading事件
created:完成了 data 数据的初始化,el没有,在这结束loading,还作一些初始化,实现函数自执行
beforeMount:完成了 el 和 data 初始化
mounted:完成挂载, 在这发起后端请求,拿回数据,配合路由钩子作一些事情
beforeDestory:销毁,执行了destroy操做,后续就再也不受vue控制了。应用:你确认删除XX吗? destroyed :当前组件已被删除,清空相关内容。
注意:不要在选项属性或回调上使用箭头函数,好比 created: () => console.log(this.a)
或 vm.$watch('a', newValue => this.myMethod())
。由于箭头函数是和父级上下文绑定在一块儿的,this
不会是如你所预期的 Vue 实例,常常致使 Uncaught TypeError: Cannot read property of undefined
或 Uncaught TypeError: this.myMethod is not a function
之类的错误。
十二、model(2.2.0新增)
容许一个自定义组件在使用 v-model
时定制 prop 和 event。默认状况下,一个组件上的 v-model
会把 value
用做 prop 且把 input
用做 event,可是一些输入类型好比单选框和复选框按钮可能想使用 value
prop 来达到不一样的目的。使用 model
选项能够回避这些状况产生的冲突。
Vue.component('my-checkbox', { model: { prop: 'checked', event: 'change' }, props: { // this allows using the `value` prop for a different purpose value: String, // use `checked` as the prop which take the place of `value` checked: { type: Number, default: 0 } }, // ... }) <my-checkbox v-model="foo" value="some value"></my-checkbox>
1三、组件
每用一次组件,就会有一个它的新实例被建立。
一个组件的 data
选项必须是一个函数。
能够调用内建的$emit方法,并传入事件的名字,来向父级组件触发一个事件。
全局注册和局部注册:
全局注册: Vue.component('my-component-name', { // ... 选项 ... }) 它们在注册以后能够用在任何新建立的 Vue 根实例 (new Vue) 的模板中 Vue.component('component-a', { /* ... */ }) Vue.component('component-b', { /* ... */ }) Vue.component('component-c', { /* ... */ }) new Vue({ el: '#app' }) html <div id="app"> <component-a></component-a> <component-b></component-b> <component-c></component-c> </div>
全局注册的弊端在于:若是你使用webpack这样的构建系统,全局注册意味着即使你再也不使用一个组件,它仍然会被包含在你最终的构建结果中。这形成了用户下载的 JavaScript 的无谓的增长。
局部注册: var ComponentA = { /* ... */ } var ComponentB = { /* ... */ } var ComponentC = { /* ... */ } 而后 new Vue({ el: '#app' components: { 'component-a': ComponentA, 'component-b': ComponentB } })
注意局部注册的组件在其子组件中不可用。例如,若是你但愿 ComponentA
在 ComponentB
中可用,则你须要这样写:
var ComponentA = { /* ... */ } var ComponentB = { components: { 'component-a': ComponentA }, // ... }
1四、slot
概述:简单来讲,假如父组件须要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪一个地方显示、如何显示,就是slot分发负责的活。
默认状况下,父组件在子组件内套的内容是不显示的:
<div id="app"> <children> <span>12345</span> <!--上面这行不会显示--> </children> </div> <script> var vm = new Vue({ el: '#app', components: { children: { template: "<button>为了明确做用范围,因此使用button标签</button>" } } }); </script> 显示内容是一个button按钮,不包含span标签里面的内容;
使用slot标签的话,能够将父组件放在子组件的内容,放到想让他显示的地方。父组件放在子组件里的内容,插到了子组件的<slot></slot>位置;即便有多个标签,会一块儿被插入,至关于用父组件放在子组件里的标签,替换了<slot></slot>这个标签。
<div id="app"> <children> <span>12345</span> <!--上面这行不会显示--> </children> </div> <script> var vm = new Vue({ el: '#app', components: { children: { //这个无返回值,不会继续派发 template: "<button><slot></slot>为了明确做用范围,因此使用button标签</button>" } } }); </script> 结果是: <button><span>12345</span>为了明确做用范围,因此使用button标签</button>
假如父组件没有在子组件中放置有标签,或者是父组件在子组件中放置标签,但有slot属性,而子组件中没有该slot属性的标签。那么,子组件的slot标签,将不会起到任何做用。
1五、provide和inject:
全部后代都须要访问同一个方法时,使用$parent没法很好扩展到更深层记得嵌套组件,可以使用上述方法。例如:
<google-map> <google-map-region v-bind:shape="cityBoundaries"> <google-map-markers v-bind:places="iceCreamShops"></google-map-markers> </google-map-region> </google-map>
全部的<google-map>后代都须要getMap方法,provide容许制定提供给后代组件的数据/方法:
provide: function () { return { getMap: this.getMap } }
而后再相应组件里使用inject接受属性。
inject: ['getMap']
1六、过渡(transition)
整个阶段有6个class过程:
v-enter:进入过渡的开始状态,元素被插入前生效,被插入后的下一帧移除;
v-enter-active:进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入以前生效,在过渡/动画完成以后移除。这个类能够被用来定义进入过渡的过程时间,延迟和曲线函数;
v-enter-to:进入过渡的结束状态。在元素被插入以后下一帧生效 ,在过渡/动画完成以后移除;
v-leave:离开过渡的开始状态。在离开过渡被触发时马上生效,下一帧被移除;
v-leave-active:离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时马上生效,在过渡/动画完成以后移除。这个类能够被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:离开过渡的结束状态。在离开过渡被触发以后下一帧生效,在过渡/动画完成以后移除。
注:若是你使用一个没有名字的 <transition>
,则 v-
是这些类名的默认前缀。若是你使用了 <transition name="my-transition">
,那么 v-enter
会替换为 my-transition-enter
动画animationend,同过渡,区别是在动画中v-enter在节点插入DOM后不回当即删除,而在animationend触发时删除。
1七、自定义指令:
使用directive建立,以下所示。
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } }) //局部指令 directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } }
1八、过滤器:
只能在双花括号内和v-bind表达式使用。定义经过filters:{}实现(或者全局的vue.filter())。