{"action":"opened","issue":{"url":"https://api.github.com/repos/scnu-kevinkong/Vue.js-/issues/4","repository_url":"https://api.github.com/repos/scnu-kevinkong/Vue.js-","labels_url":"https://api.github.com/repos/scnu-kevinkong/Vue.js-/issues/4/labels{/name}","comments_url":"https://api.github.com/repos/scnu-kevinkong/Vue.js-/issues/4/comments","events_url":"https://api.github.com/repos/scnu-kevinkong/Vue.js-/issues/4/events","html_url":"https://github.com/scnu-kevinkong/Vue.js-/issues/4","id":369978445,"node_id":"MDU6SXNzdWUzNjk5Nzg0NDU=","number":4,"title":"Vue中的生命周期","user":{"login":"scnu-kevinkong","id":38560299,"node_id":"MDQ6VXNlcjM4NTYwMjk5","avatar_url":"https://avatars3.githubusercontent.com/u/38560299?v=4","gravatar_id":"","url":"https://api.github.com/users/scnu-kevinkong","html_url":"https://github.com/scnu-kevinkong","followers_url":"https://api.github.com/users/scnu-kevinkong/followers","following_url":"https://api.github.com/users/scnu-kevinkong/following{/other_user}","gists_url":"https://api.github.com/users/scnu-kevinkong/gists{/gist_id}","starred_url":"https://api.github.com/users/scnu-kevinkong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scnu-kevinkong/subscriptions","organizations_url":"https://api.github.com/users/scnu-kevinkong/orgs","repos_url":"https://api.github.com/users/scnu-kevinkong/repos","events_url":"https://api.github.com/users/scnu-kevinkong/events{/privacy}","received_events_url":"https://api.github.com/users/scnu-kevinkong/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-10-15T02:45:50Z","updated_at":"2018-10-15T02:45:50Z","closed_at":null,"author_association":"OWNER","body":"> 一个 Vue 实例在被创建时都要经过一系列的初始化过程——例如，需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数，这给了用户在不同阶段添加自己的代码的机会。\r\n\r\n# 生命周期图示\r\n下图展示了实例的生命周期。你不需要立马弄明白所有的东西，不过随着你的不断学习和使用，它的参考价值会越来越高。\r\n![image](https://user-images.githubusercontent.com/38560299/46927074-4b197000-d066-11e8-95cb-b84603026fc2.png)\r\n\r\n# 生命周期列表\r\n参考连接 https://juejin.im/post/5afd7eb16fb9a07ac5605bb3​\r\n\r\n## beforeCreate\r\n![image](https://user-images.githubusercontent.com/38560299/46927084-5c627c80-d066-11e8-94f6-040dc5109b20.png)\r\n\r\n在实例初始化之后，数据观测和暴露了一些有用的实例属性与方法。\r\n\r\n实例初始化——new Vue()\r\n\r\n数据观测——在vue的响应式系统中加入data对象中所有数据，这边涉及到vue的双向绑定，可以看官方文档上的这篇深度响应式原理 深度响应式原理​\r\n\r\n暴露属性和方法——就是vue实例自带的一些属性和方法，我们可以看一个官网的例子，例子中带$的属性和方法就是vue实例自带的，可以和用户定义的区分开来\r\n\r\nvar data = { a: 1 }\r\nvar vm = new Vue({\r\n  el: '#example',\r\n  data: data\r\n})\r\n​\r\nvm.$data === data // => true\r\nvm.$el === document.getElementById('example') // => true\r\n​\r\n// $watch 是一个实例方法\r\nvm.$watch('a', function (newValue, oldValue) {\r\n  // 这个回调将在 `vm.a` 改变后调用\r\n})\r\n\r\n## created\r\n- el属性对生命周期的影响\r\n\r\n![image](https://user-images.githubusercontent.com/38560299/46927109-73a16a00-d066-11e8-8618-b217d741ab46.png)\r\n\r\n- 有el属性的情况下\r\nnew Vue({\r\nel: '#app',\r\nbeforeCreate: function() {\r\n  console.log('调用了beforeCreate')\r\n},\r\ncreated: function() {\r\n  console.log('调用了created')\r\n},\r\nbeforeMount: function() {\r\n  console.log('调用了beforeMount')\r\n},\r\nmounted: function() {\r\n  console.log('调用了mounted')\r\n}\r\n})\r\n​\r\n// 输出结果\r\n// 调用了beforeCreate\r\n// 调用了created\r\n// 调用了beforeMount\r\n// 调用了mounted\r\n\r\n- 在没有el属性的情况下，没有vm.$mount\r\n\r\nnew Vue({\r\nbeforeCreate: function() {\r\n  console.log('调用了beforeCreate')\r\n},\r\ncreated: function() {\r\n  console.log('调用了created')\r\n},\r\nbeforeMount: function() {\r\n  console.log('调用了beforeMount')\r\n},\r\nmounted: function() {\r\n  console.log('调用了mounted')\r\n}\r\n})\r\n​\r\n// 输出结果\r\n// 调用了beforeCreate\r\n// 调用了created\r\n\r\n- 在没有el属性的情况下，但是有vm.$mount方法\r\nvar vm = new Vue({\r\nbeforeCreate: function() {\r\n  console.log('调用了beforeCreate')\r\n},\r\ncreated: function() {\r\n  console.log('调用了created')\r\n},\r\nbeforeMount: function() {\r\n  console.log('调用了beforeMount')\r\n},\r\nmounted: function() {\r\n  console.log('调用了mounted')\r\n}\r\n})\r\n​\r\nvm.$mount('#app')\r\n​\r\n// 输出结果\r\n// 调用了beforeCreate\r\n// 调用了created\r\n// 调用了beforeMount\r\n// 调用了mounted\r\n\r\n- template属性对生命周期的影响\r\n![image](https://user-images.githubusercontent.com/38560299/46927147-9a5fa080-d066-11e8-8f4c-e804598c76c8.png)\r\n\r\n这里面分三种情况：\r\n1. 在实例内部有template属性的时候，直接用内部的，然后调用render函数去渲染。\r\n2. 在实例内部没有找到template，就调用外部的html。实例内部的template属性比外部的优先级高。\r\n3. 要是前两者都不满足，那么就抛出错误。\r\n\r\n我们来看以下几个例子：\r\n- 没有id\r\nnew Vue({\r\n  el: '#app',\r\n  template: '<div id=\"app\">hello world</div>'\r\n})\r\n- 没有template\r\n<div id=\"app\">hello world</div>\r\n​\r\nnew Vue({\r\n  el: '#app'\r\n})\r\n\r\n- 两者都存在的时候\r\n<div id=\"app\">hello world2</div>\r\n​\r\nnew Vue({\r\n  el: '#app',\r\n  template: '<div id=\"app\">hello world1</div>'\r\n})\r\n\r\n>  从上述的例子可以看出内部的优先外部的。\r\n\r\n- 关于这个生命周期中的一些问题\r\n1、为什么el属性的判断在template之前？ 因为el是一个选择器，比如上述例子中我们用到的最多的是id选择器app，vue实例需要用这个el去template中寻找对应的。\r\n\r\n2、实际上，vue实例中还有一种render选项，我们可以从文档上看一下他的用法：\r\n\r\nnew Vue({\r\n  el: '#app',\r\n  render() {\r\n    return (...)\r\n  }\r\n})\r\n\r\n3、上述三者的渲染优先级：render函数 > template属性 > 外部html\r\n\r\n4、vue编译过程——把tempalte编译成render函数的过程。\r\n\r\n## beforeMount &&  mounted\r\n\r\n![image](https://user-images.githubusercontent.com/38560299/46927266-1ce86000-d067-11e8-996c-acd360394a58.png)\r\n\r\n我们先来看一个例子\r\n\r\n<div id=\"app\">\r\n  <p>{{message}}</p>\r\n</div>\r\n​\r\nnew Vue({\r\n  el: '#app',\r\n  data: {\r\n    message: 1\r\n  },\r\n  beforeMount: function() {\r\n    console.log('调用了beforeMount');\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  mounted: function() {\r\n    console.log('调用了mounted');\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  }\r\n})\r\n​\r\n// 输出的结果：\r\n// 调用了beforeMount\r\n// 1\r\n// <div>\r\n// </div>\r\n​\r\n// 调用了mounted\r\n// 1\r\n// <div id=\"app\">\r\n//  <p>1</p>\r\n// </div>\r\n\r\n> 创建vue实例的$el，然后用它替代el属性。\r\n\r\n## beforeUpdate && updated\r\n![image](https://user-images.githubusercontent.com/38560299/46927295-38ec0180-d067-11e8-9043-a9866b07fda7.png)\r\n\r\n> 这个过程中，我们会发现，当一个数据发生改变时，你的视图也将随之改变，整个更新的过程是：数据改变——导致虚拟DOM的改变——调用这两个生命钩子去改变视图 \r\n\r\n- 重点：这个数据只有和模版中的数据绑定了才会发生更新\r\n\r\n// 没绑定的情况\r\n​\r\nvar vm = new Vue({\r\n  el: '#app',\r\n  template: '<div id=\"app\"></div>',\r\n  beforeUpdate: function() {\r\n    console.log('调用了beforeUpdate')\r\n  },\r\n  updated: function() {\r\n    console.log('调用了uodated')\r\n  },\r\n  data: {\r\n    a: 1\r\n  }\r\n})\r\n​\r\nvm.a = 2\r\n//这种情况在控制台中是什么都不会输出的。\r\n\r\nvar vm = new Vue({\r\n  el: '#app',\r\n  template: '<div id=\"app\">{{a}}</div>',\r\n  beforeUpdate: function() {\r\n    console.log('调用了beforeUpdate')\r\n  },\r\n  updated: function() {\r\n    console.log('调用了uodated')\r\n  },\r\n  data: {\r\n    a: 1\r\n  }\r\n})\r\n​\r\nvm.a = 2\r\n​\r\n// 输出结果：\r\n// 调用了beforeUpdate\r\n// 调用了uodated\r\n\r\n## beforeDestory && destoryed\r\n\r\n![image](https://user-images.githubusercontent.com/38560299/46927317-50c38580-d067-11e8-8fca-09ad70223f9e.png)\r\n\r\n> 在beferoDestory生命钩子调用之前，所有实例都可以用，但是当调用后，Vue 实例指示的所有东西都会解绑定，所有的事件监听器会被移除，所有的子实例也会被销毁。\r\n\r\n## 几个不常用的生命钩子\r\n- activated：当组件激活的时候调用\r\n- deactivated：当组件停用的时候调用\r\n- errorCaptured：这个生命钩子可以看官网，2.5.0之后才有的。当捕获一个来自子孙组件的错误时被调用。\r\n\r\n## 最后我们用一个例子来过一遍生命周期\r\n\r\nlet vm = new Vue({\r\n  el: '#app',\r\n  data: {\r\n    message: 1\r\n  },\r\n  template: '<div id=\"app\"><p>{{message}}</p></div>',\r\n  beforeCreate() {\r\n    console.log('调用了beforeCreate')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  created() {\r\n    console.log('调用了created')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  beforeMount() {\r\n    console.log('调用了beforeMount')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  mounted() {\r\n    console.log('调用了mounted')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  beforeUpdate() {\r\n    console.log('调用了beforeUpdate')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  updated() {\r\n    console.log('调用了updated')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  beforeDestory() {\r\n    console.log('调用了beforeDestory')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  },\r\n  destoryed() {\r\n    console.log('调用了Destoryed')\r\n    console.log(this.message)\r\n    console.log(this.$el)\r\n  }\r\n})\r\n​\r\nvm.message = 2\r\n\r\n- 输出的结果：\r\n\r\n// 调用了beforeCreate\r\n// undefined\r\n// undefined\r\n// 调用了created\r\n// 1\r\n// undefined\r\n// 调用了beforeMount\r\n// 1\r\n// <div></div>\r\n// 调用了mounted\r\n// 1\r\n// <div id=\"app\"><p>1</p></div>\r\n// 调用了beforeUpdate\r\n// 2\r\n// <div id=\"app\"><p>2</p></div>\r\n// 调用了updated\r\n// 2\r\n// <div id=\"app\"><p>2</p></div>\r\n\r\n> 不要在选项属性或回调上使用箭头函数，比如 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 之类的错误。"}}
{"actor":{"display_login":"scnu-kevinkong"}}