vue 的生命周期主要分为几个简单, 数据初始化, dom 挂载, 数据更新, 组件卸载, 在一个就是开启了组件缓存的时候, 会有组件启用和组件停用阶段, 每个阶段都去前后两个钩子除了缓存的那俩
数据初始化阶段
beforeCreate: 在实例初始化之后, 数据观测 (data observer) 和 event/watcher 事件配置之前被调用.
created: 实例已经创建完成之后被调用. 在这一步, 实例已完成以下的配置: 数据观测 (data observer), 属性和方法的运算, watch/event 事件回调. 然而, 挂载阶段还没开始,$el 属性目前不可见.
dom 挂载阶段
beforeMount: 在挂载开始之前被调用: 相关的 render 函数首次被调用.
mounted:el 被新创建的 vm.$el 替换, 并挂载到实例上去之后调用该钩子. 如果 root 实例挂载了一个文档内元素, 当 mounted 被调用时 vm.$el 也在文档内.
mounted 不会承诺所有的子组件也都一起被挂载. 如果你希望等到整个视图都渲染完毕, 可以用 vm.$nextTick 替换掉 mounted
数据跟新阶段
beforeUpdate: 数据更新时调用, 发生在虚拟 DOM 重新渲染和打补丁之前.
updated: 由于数据更改导致的虚拟 DOM 重新渲染和打补丁, 在这之后会调用该钩子.
当这个钩子被调用时, 组件 DOM 已经更新, 所以你现在可以执行依赖于 DOM 的操作. 然而在大多数情况下, 你应该避免在此期间更改状态. 如果要相应状态改变, 通常最好使用计算属性或 watcher 取而代之.
updated 不会承诺所有的子组件也都一起被重绘. 如果你希望等到整个视图都重绘完毕, 可以用 vm.$nextTick 替换掉 updated:
缓存启用的时候会有下面两个钩子
activated:keep-alive 组件激活时调用.
deactivated:keep-alive 组件停用时调用.
组件卸载的时候:
beforeDestroy: 实例销毁之前调用. 在这一步, 实例仍然完全可用.
destroyed:Vue 实例销毁后调用. 调用后, Vue 实例指示的所有东西都会解绑定, 所有的事件监听器会被移除, 所有的子实例也会被销毁.
vue.PNG
2.Vue 实现数据双向绑定的原理
vue 实现数据双向绑定主要是采用数据劫持结合发布者 - 订阅者模式的方式, 通过 Object.defineProperty()来劫持各个属性的 setter,getter, 在数据变动时发布消息给订阅者, 触发相应的监听回调. 具体话其实就是通过 Obeject.defineProperty() 中的 setter 和 getter 来监听属性变动实现 Observer 进行数据的监听然后就是通知订阅者, 那么订阅者其实就是简单的一个数组, 这个数组中的内容就是我门使用了的一个数据的集合, 使用了的数据可以通过 getter 得到, 其实就是在调用的时候给数组里面添加一个订阅者这样就是实现了一个 Watcher(需要监听的数据的集合), 然后在实现一个 Compile 其作用就是解析模板指令, 将模板中的变量替换成数据, 然后初始化渲染页面视图, 并将每个指令对应的节点绑定更新函数, 添加监听数据的订阅者, 一旦数据有变动, 收到通知, 更新视图, 其实 vue 的数据双向绑定就是 MVVM 作为数据绑定的入口, 整合 Observer,Compile 和 Watcher 三者, 通过 Observer 来监听自己的 model 数据变化, 通过 Compile 来解析编译模板指令, 最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁, 达到数据变化 -> 视图更新; 视图交互变化(input) -> 数据 model 变更的双向绑定效果.
3.Vue 路由的实现原理
在 vue 中路由主要有 hash 与 History interface 两种方式实现前端路由, 单页路由的特点就是采用前端路由系统, 通过改变 URL, 在不重新请求页面的情况下, 更新页面视图. 目前在浏览器环境中这一功能的实现主要有两种方式: hash 和 History interface, 这两种模式的实现分别是
先说 hash, 在浏览器的 url 中 hash("#")符号的本来作用是加在 URL 中指示网页中的位置:# 符号本身以及它后面的字符称之为 hash, 可通过 Windows.location.hash 属性读取. 它具几个特点就是: hash 虽然出现在 URL 中, 但不会被包括在 HTTP 请求中. 它是用来指导浏览器动作的, 对服务器端完全无用, 因此, 改变 hash 不会重新加载页面, 并且可以为 hash 的改变添加 hashchange 监听事件, 在一个就是每一次改变 hash(Windows.location.hash), 都会在浏览器的访问历史中增加一个记录, 我就可以通过他的这几个特点实现一个 hash 模式的单页路由, 通过对 location.hash 的修改实现 push 方法 (跳转页面), 通过对 location.href 的修改实现 replace() 方法, 通过对 hashchange 事件的监听实现页面跳转后的数据更新
而 History 模式则是完全采用了 h5 的新特性, 从 html5 开始, History interface 提供了两个新的方法: pushState(), replaceState()使得我们可以对浏览器历史记录栈进行修改, 以及 popState 事件可以监听到状态的变更
不过 history 模式有一个问题就是
对于单页应用来讲, 理想的使用场景是仅在进入应用时加载 index.HTML, 后续在的网络操作通过 Ajax 完成, 不会根据 URL 重新请求页面, 但是如果用户直接在地址栏中输入并回车, 浏览器重启重新加载的时候 history 模式则会将 URL 修改得就和正常请求后端的 URL 一样, 在此情况下重新向后端发送请求, 如后端没有配置对应 的路由处理, 则会返回 404 错误. 这种问题的解决, 一般情况下我们都是在后端进行配置, 将所有的路由请求都指向 index.HTML 文件
4.Vue 组建的通讯
1. 父组件传子组件
单项数据流 props
使用 refs 访问子组件
使用 $parent 访问父组件
使用 $children 访问子组件
使用 $root 访问当前组件树的根 Vue 实例
在 template 元素使用 scope 可以访问到子组件中 slot 元素的属性值 要 13k
2. 子组件传递数据给父组件:
子组件通过事件给父组件传数据, 子组件通过 $emit(eventName)触发事件, 父组件通过 $on 监听事件
3. 兄弟组件间通信
1用事件发布订阅 var bus=new vue();bus.$emit("id-selected",1);bus.$on("id-selected",function(id){})
2用 vuex 来实现
5.VueX 是做什么的
Vuex 是适用于 vue.js 应用的状态管理库, 为应用中的所有组件提供集中式的状态存储与操作, 保证了所有状态以可预测的方式进行修改;
state: state 定义了应用状态的数据结构, 同样可以在这里设置默认的初始状态.
actions:Actions 即是定义提交触发更改信息的描述, 常见的例子有从服务端获取数据, 在数据获取完成后会调用 store.commit()来调用更改 Store 中的状态. 可以在组件中使用 dispatch 来发出 Actions.
mutations: 调用 mutations 是唯一允许更新应用状态的地方.
getters: Getters 允许组件从 Store 中获取数据, 譬如我们可以从 Store 中的 projectList 中筛选出已完成的项目列表
modules: modules 对象允许将单一的 Store 拆分为多个 Store 的同时保存在单一的状态树中. 随着应用复杂度的增加, 这种拆分能够更好地组织代码
但是 vuex 也有缺点就是, vuex 中保存的数据是和网页的生命周期同步的, 当执行页面刷新的时候 vuex 中所有数据都会消失复位到初始状态, 所以不太适合做有分享页面的数据交互(在这种项目中 vuex 只适合数据的集中管理, 不适合数据的存储, 这种情况一般是使用路由传递参数会好一些), 适合后台管理系统多一些, 后台管理系统一般都是公司内部使用;
6.Vue 的路由如何传参?
- <router-link :to="{path:'details',query: {id:el.tog_line_id}}">
- <router-link :to="{name:'details',params: {id:el.tog_line_id}}">
然后在组件内部通过 $route.params 来读取数据, 但是路由传递的参数值是对象的话就不行了会报错, 一般都是在传递之前先吧需要传递的数据使用 base64 转化一下就不会造成路由报错了
7.Vue 和 angular 的区别?
1. 在 API 与设计两方面上 Vue.JS 都比 Angular 简单得多, 因此你可以快速地掌握它的全部特性并投入开发.
2.Vue.JS 是一个更加灵活开放的解决方案. 它允许你以希望的方式组织应用程序, 而不是任何时候都必须遵循 Angular 制定的规则. 它仅仅是一个视图层, 所以你可以将它嵌入一个现有页面而不一定要做成一个庞大的单页应用. 在配合其他库方面它给了你更大的的空间, 但相应, 你也需要做更多的架构决策. 例如, Vue.JS 核心默认不包含路由和 Ajax 功能, 并且通常假定你在应用中使用了一个模块构建系统. 这可能是最重要的区别.
3.Angular 使用双向绑定, Vue 也支持双向绑定, 不过默认为单向绑定, 数据从父组件单向传给子组件. 在大型应用中使用单向绑定让数据流易于理解.
4. 在 Vue.JS 中指令和组件分得更清晰. 指令只封装 DOM 操作, 而组件代表一个自给自足的独立单元 -- 有自己的视图和数据逻辑. 在 Angular 中两者有不少相混的地方.
5.Vue.JS 有更好的性能, 并且非常非常容易优化, 因为它不使用脏检查. Angular, 当 watcher 越来越多时会变得越来越慢, 因为作用域内的每一次变化, 所有 watcher 都要重新计算. 并且, 如果一些 watcher 触发另一个更新, 脏检查循环 (digest cycle) 可能要运行多次. Angular 用户常常要使用深奥的技术, 以解决脏检查循环的问题. 有时没有简单的办法来优化有大量 watcher 的作用域. Vue.JS 则根本没有这个问题, 因为它使用基于依赖追踪的观察系统并且异步列队更新, 所有的数据变化都是独立地触发, 除非它们之间有明确的依赖关系. 唯一需要做的优化是在 v-for 上使用 track-by.
8. 指令 keep-alive
指令 keep-alive 是做组件缓存的, 就是把组件缓存起来不会销毁, 下次打开这个组件直接显示出来, 如果把切换出去的组件保留在内存中, 可以保留它的状态或避免重新渲染. 一般用于有上拉加载的页面, 因为如果一个页面有上啦加载的话, 用户加载了好几页了都然后点击进入详情, 在返回又得重新加载, 这个体验很不好, 有了 keep-alive 后就可以吧这个列表页面保存在内存中避免用户的重复操作, 增强用户体验.
9. 关于 vuejs 页面闪烁{{message}}
在 Vue.JS 指令中有 v-cloak, 这个指令保持在元素上直到关联实例结束编译. 和 CSS 规则如 [v-cloak]{display:none} 一起用时, 这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕. 用法如下:
- [v-cloak]{
- display:none;
- }
- <div v-cloak>{{message}}</div>
这样 < div > 不会显示, 直到编译结束
10.watch,computed,methods 的区别?
watch 是做单一的数据监听, 方法名字必须和需要监听的数据同名, 不需要返回值, 可以得到数据修改前后修改后的值
computed 和 methods 基本相同, 都是方法, 都是在数据改变的时候如果方法内部有该数据的依赖都是自动执行,
但是它们俩定位不同, computed 是计算属性, 而 methods 是放的操作方法,
还有就是调用形式不同, 计算属性调用不需要加括弧, methods 则需要加()
在一个就是 computed 会将计算的值进行缓存, 如果方法内部依赖的值没有发生变化调用 computed 不管多少次都只是执行一次, 其他调用反回的是缓存的值, 而 methods 则调用多少次就会执行多少次
来源: http://www.jianshu.com/p/2f8f85936c24