一、生命周期
1.生命周期图示:
2.生命周期钩子函数
-
- beforeCreate
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
- beforeCreate
2.created
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
数据观测指的是:Vue中的data选项。
注意:在上图中,调用完created()方法后,会判断是否有“el”选项,若没有就调用vm.$mount(el)方法。如下:<code> var app = new Vue({ // el: '#app', template: '<h1>Hello Vue - {{value}}</h1>', data: { value: 1 } } document.onclick = function() { app.$mount('#app'); console.log(app); } </code>
- 3.beforeMount
在挂载开始之前被调用:相关的 render 函数首次被调用。
4.mounted
el 被新创建的 vm. el替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当mounted被调用时vm. el 也在文档内。
注意 mounted 不会承诺所有的子组件也都一起被挂载。“文档”指的是HTML。
- 5.beforeUpdate
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
- 6.updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 - 7.beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。 8.destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
注意:vue实例销毁共有两种方式:
- 关闭浏览器,自动会销毁;
- 调用vm.$destroy()的实例方法,完全销毁一个实例。
3.钩子函数应用
1.created
使用场景:当页面一打开,就需要向后端请求到数据并渲染到页面中。
要满足上面所说的需求,那就需要在created()钩子函数内发送请求。<code> <div id="app"> <ul> <li v-for="data in news">{{data.title}}</li> </ul> </div> <script src="js/fetch-jsonp.js" charset="utf-8"></script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { url: 'https://3g.163.com/touch/jsonp/sy/recommend/0-10.html?hasad=1&offset=0&size=10', news: [] }, created() { //console.log(this.news); // this.getNews(this.url); //方法二: fetchJsonp(this.url, { jsonpCallback: 'callback', jsonpCallbackFunction: 'miaov123' }) .then( response => { console.log(response); return response.json(); } ) .then( data => { console.log(data); this.news = data.news; } ) }, //方法一: methods: { // 通过JSONP发送请求,拿取数据 getNews(url) { var script = document.createElement('script'); script.src = url; document.body.appendChild(script); window.miaov = (data) => { this.news = data.news; } } } }); </script> </code>
说明:
- fetch-jsonp.js是一个封装好的JSONP的框架,可以直接拿来用;
- 由于”script.src=url”,这一步是一个异步非阻塞过程,在该步没有执行完成,就会执行后面的代码声明一个window上的函数。这样等到该过程执行完后端会返回一个“miaov(data)”函数调用的表达式时,js就能正确解析它;否则,若是同步阻塞,等到该过程完成得到“miaov(data)”函数调用,此时,js中“miaov”函数还没声明,那么就无法正确解析而会报错;
- link/script/img等需要加载资源的标签,都是异步,通知机制是onload事件;
- script标签在html中,引入其他文件时,执行是同步阻塞,在script标签中写入js代码,执行时是异步非阻塞。
- window.miaov=(function(){…}),此代码是将一个名为”miaov”的函数挂在window对象上,但是该函数体里的代码的作用域还是在当下环境内,并没有变成全局。
2.实现实时发送请求
<code> <div id="app"> <input type="text" v-model="keyword" /> <ul> <li v-for="data in list">{{data[0]}}</li> </ul> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { keyword: '', list: [] }, watch: { keyword() { //console.log(this.keyword); // 发送请求 fetchJsonp('https://suggest.taobao.com/sug?code=utf-8&q=' + this.keyword, { jsonpCallback: 'callback', jsonpCallbackFunction: 'miaov123' }).then( response => { <!--得到请求对象,并把该对象解析成JSON对象数据--> // 解析数据的过程也是异步操作 return response.json(); //json方法的返回值也是promise对象 } ).then( data => { this.list = data.result; } ); } } }); </code>
注意:
- 1.用户在input中输入“keyword”时,“keyword”在不断变化,那么js就需要根据“keyword”的变化,发送“keyword”不同的请求给服务端。那么此时需要监控“keyword”来作出相应的动作(请求)。
2.在vue中本来有两种方式去实现根据当前值的变化修改其他值,即watch和computed。但是computed属性不支持异步的写法,如下:
<code> computed: { async a() { var response = await fetchJsonp('https://suggest.taobao.com/sug?code=utf-8&q=' + this.keyword, { jsonpCallback: 'callback', jsonpCallbackFunction: 'miaov123' }) var data = await response.json();//await代替then方法 return data; } } </code>
即“async a”这种写法不支持。
二、自定义指令
有的情况下,你仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令。
1.注册自定义指令
- 注册全局自定义指令
Vue.directive(指令名称,{指令配置}); 注自定义册局部指令
<code> directives: { focus: { // 指令的定义--- inserted: function (el) {} } } </code>
- 指令名称不需要使用v-前缀,但是在使用的时候需要添加。
- 注册全局自定义指令
2.指令中也提供一些配置,这些配置是一些钩子函数(生命周期函数是一个意思)
- bind
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- bind
- inserted
被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
该元素添加到页面,会调用此钩子函数
- update
所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。
指令中使用的数据发生变化,会调用此钩子函数。
- componetnUpdated
所在组件的 VNode 及其孩子的 VNode 全部更新时调用。 - unbind
只调用一次,指令与元素解绑时调用。
3.钩子函数还可以接收一些参数,包括:
- el
指令所绑定的元素,可以用来直接操作 DOM 。
- binding
写法:v-name:args.modifiers=”value”;
一个对象,包含以下属性:
(1)name:指令名,不包括 v- 前缀。
(2)value:指令的绑定值,例如:v-my-directive=”1 + 1”, value 的值是 2。
(3)oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
(4)expression:绑定值的字符串形式。例如 v-my-directive=”1 + 1” ,expression 的值是 “1 + 1”。
(5)arg:传给指令的参数。例如 v-my-directive:foo,arg 的值是 “foo”。
(6)modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。 - vnode
Vue 编译生成的虚拟节点。 oldVnode
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
- el