v-show 和 v-if 都能控制元素的显示和隐藏。
v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏
v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
v-show 其实就是在控制 css
v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件
v-show 只编译一次,后面其实就是控制 css。
v-if 不停的销毁和创建,故 v-show性能更好。
如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都会进行渲染,此
后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销较大)。
如果不需要频繁切换某节点时,使用 v-if(因为懒加载,初始为 false 时,不会渲染,但是因为它是通过添加和删除 dom 元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)。
增加Key可以标识组件的唯一性,key的作用主要是为了高效的更新虚拟DOM
1、assets和static两个都是用于存放静态资源文件。
2、放在static中的文件不会进行构建编译处理,也就不会压缩体积,在打包时效率会更高,但体积更大在服务器中就会占据更大的空间。
3、放在assets中的文件会进行压缩体积、代码格式化,压缩后会放置在static中一同上传服务器。
4、因此建议样式文件放在assets中进行打包,引入的第三方文件放到static中,因为引入的文件已经做过打包处理。
1、单页面应用(SPA):通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
2、多页面(MPA):就是指一个应用中有多个页面,页面跳转时是整页刷新。
单页面的优点:
1,用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
2,前后端分离
3,页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
1,不利于seo
2,导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
3,初次加载时耗时多
4,页面复杂度提高很多
1、直接给相应的元素加id,然后再document.getElementById(“id”);获取,然后设置相应属性或样式。
2、使用ref,给相应的元素加ref=“name” 然后再this.$refs.name获取到该元素,并且可以直接调用子组件中定义的方法。
assets文件夹是放静态资源;
components是放组件;
router是定义路由相关的配置;
view视图;
app.vue是一个应用主组件;
main.js是入口文件
this.nextTick()将回调延迟到下次 DOM 更新循环之后执行。
在修改数据之后立即使用它,然后等待 DOM 更新。
它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
在 new Vue() 中,data 是可以作为一个对象进行操作的,然而在 component 中,data 只能以函数的形式存在,不能直接将对象赋值给它。
Vue生命周期相关
概念:Vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。
作用:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
1、beforeCreat()
:创建前 在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在此生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
2、 created()
:被创建 data 和 methods都已经被初始化好了,可以调用了
3、beforeMount()
:挂载前 在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
4、mounted()
:已挂载 Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
5、beforeupdate():
更新前 页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
6、updated()
:更新 页面显示的数据和data中的数据已经保持同步了,都是最新的
7、beforeDestroy()
: 销毁前 Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
8、destroyed()
:被销毁 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子。
1、beforecreate
: 可以在这加个loading事件,在加载实例时触发
2、created
: 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
3、mounted
: 挂载元素,获取到DOM节点
4、updated
: 如果对数据统一处理,在这里写上相应函数
5、beforeDestroy
: 可以做一个确认停止事件的确认框
6、nextTick
: 更新数据后立即操作dom
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
mounted
Vuex相关
1、概念:只用来读取的状态集中放在store中;
改变状态的方式是提交mutations,这是个同步的事物;
异步逻辑应该封装在action中。
2、使用:在main.js引入store,注入。新建了一个目录store,…… export 。
3、场景:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车。
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
有五种,分别是 State、 Getter、Mutation 、Action、 Module
1、state => 基本数据(数据源存放地)
2、getters => 从基本数据派生出来的数据
3、mutations => 提交更改数据的方法,同步!
4、actions => 像一个装饰器,包裹mutations,使之可以异步。
5、modules => 模块化Vuex
1、可维护性会下降,想修改数据要维护三个地方;
2、可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
3、增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
1、Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2、Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:
store.commit(‘increment’)
Action Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。 让我们来注册一个简单的 action:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。
实践中,我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit 很多次的时候):
actions: {
increment ({ commit }) {
commit('increment')
}
}
vue.js的两大核心:数据驱动和组件系统
1、数据驱动,也就是数据的双向绑定
1、Vue 响应式核心就是,getter 的时候会收集依赖,setter 的时候会触发依赖更新
2、vue将遍历data中对象的所有property,并使用Object.defineProperty
把这些 property 全部转为 getter/setter。
3、这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
4、每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。
5、getter 的时候我们会收集依赖,依赖收集就是订阅数据变化watcher的收集,依赖收集的目的是当响应式数据发生变化时,能够通知相应的订阅者去处理相关的逻辑。
6、setter 的时候会触发依赖更新,之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
2、组件系统,组件的核心选项
1、模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
2、初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。
3、接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。
4、方法(methods):对数据的改动操作一般都在组件的方法内进行。
5、生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。
6、私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用
MVX框架模式:MVC+MVP+MVVM
1、MVC:
1、Model(模型)+View(视图)+controller(控制器),主要是基于分层的目的,让彼此的职责分开。
2、View通过Controller来和Model联系,Controller是View和Model的协调者,View和Model不直接联系,基本联系都是单向的。
3、用户User通过控制器Controller来操作模板Model从而达到视图View的变化。
2、MVP
1、是从MVC模式演变而来的,都是通过Controller/Presenter负责逻辑的处理+Model提供数据+View负责显示。
2、在MVP中,Presenter完全把View和Model进行了分离,主要的程序逻辑在Presenter里实现。
3、并且,Presenter和View是没有直接关联的,是通过定义好的接口进行交互,从而使得在变更View的时候可以保持Presenter不变。
MVP模式的框架:Riot,js。
3、MVVM
1、MVVM是把MVC里的Controller和MVP里的Presenter改成了ViewModel。Model+View+ViewModel。
2、View的变化会自动更新到Model, Model的变化也会自动同步到View上显示。
3、这种自动同步是因为ViewModel中的属性实现了Observer,当属性变更时都能触发对应的操作。
1、看到了上面的框架模式介绍,我们可以知道它是属于MVVM模式的框架。那它有哪些特性呢?
2、其实Vue.js不是一个框架,因为它只聚焦视图层,是一个构建数据驱动的Web界面的库。
3、Vue.js通过简单的API(应用程序编程接口)提供高效的数据绑定和灵活的组件系统。
Vue.js的特性如下:
1、轻量级的框架
2、双向数据绑定
3、指令
4、插件化
相同点:
1、都支持指令:内置指令和自定义指令。
2、都支持过滤器:内置过滤器和自定义过滤器。
3、都支持双向数据绑定。
4、都不支持低端浏览器。
不同点:
1、AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观。
2、在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢。
3、Vue.js使用基于依赖追踪的观察并且使用异步队列更新。所有的数据都是独立触发的。
4、对于庞大的应用来说,这个优化差异还是比较明显的。
相同点:
1、React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用。
2、中心思想相同:一切都是组件,组件实例之间可以嵌套。
3、都提供合理的钩子函数,可以让开发者定制化地去处理需求。
4、都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载。
5、在组件开发中都支持mixins的特性。
不同点:
1、React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果做脏检查。
2、Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。
由于在浏览器中操作DOM是很昂贵的。频繁操作DOM,会产生一定性能问题。这就是虚拟Dom的产生原因。Vue2的Virtual DOM 借鉴了开源库 snabbdom 的实现。Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点,是对真实DOM的一层抽象。
优点:
1、保证性能下限:框架的虚拟DOM需要适配任何上层API可能产生的操作,他的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,既保证性能的下限。
2、无需手动操作DOM:我们不需手动去操作DOM,只需要写好 View-Model的 代码逻辑,框架会根据虚拟DOM和数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率。
3、跨平台:虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器端渲染、weex开发等等。
缺点:
1、无法进行极致优化:虽然虚拟DOM + 合理的优化,足以应对大部分应用的性能需要,但在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化。
2、首次渲染大量DOM时,由于多了一层DOM计算,会比innerHTML插入慢。
v-model 只是语法糖而已。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件。
1、 text 和 textarea 元素使用 value property 和 input 事件;
2、 checkbox 和 radio 使用 checked property 和 change事件;
3、 select 字段将 value 作为 prop 并将 change 作为事件。
注意:对于需要使用输入法的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。
在普通元素上:
input v-model='testName'
input v-bind:value='testName' v-on:input='testName = $event.target.value'
1、对象层级不要过深,否则性能就会差。
2、不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
3、v-if 和 v-show 区分使用场景
4、computed 和 watch 区分场景使用
5、v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
6、大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
7、防止内部泄露,组件销毁后把全局变量和时间销毁
8、图片懒加载
9、路由懒加载
10、异步路由
11、第三方插件的按需加载
12、适当采用 keep-alive 缓存组件
13、防抖、节流的运用
14、服务端渲染 SSR or 预渲染
这里知识针对Vue的性能优化,没有阐述其他方面的。