vue(生命周期,钩子方法,组件)
VUE实例的生命周期和VUE提供的钩子方法
钩子方法就是事先给你准备好的方法,但是需要你自己实现
盗官方的图,真香!
红色框子里的英文就代表我们可以使用钩子方法的方法名
注意事项:
不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a)
或 vm.$watch('a', newValue => this.myMethod())
。因为箭头函数并没有 this
,this
会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined
或 Uncaught TypeError: this.myMethod is not a function
之类的错误。
new Vue({
el:"#app",
data:{},
methods:{},
created:function(){
console.log("执行created方法")
},
mounted:function(){
console.log("执行mounted方法")
}
})
组件
组件是可以复用的VUE实例
组件的命名规范,单词首字母大写(例如ButtonCounter)或者全小写使用连接线(例如button-counter)
最简单的使用方法,注释解决了一个坑
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div> <script> //定义一个组件 此方式代表全局注册 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你点一下我就加一,现在是:{{ count }}</button>' }); new Vue({el:"#app"});<!--实例要写在组件定义之后--> </script> </body> </html>
每用一次组件都会创建一个新的实例,互不干扰
这是因为data的选项是一个必须是一个函数,因此每个实例可以维护一份被返回对象的独立拷贝
data: function () {
return {
count: 0
}
}
如下写法导致多个实例共用一个对象值
data: {
count: 0
}
通过 Prop 向子组件传递数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> <blog-post title="这就是传过来的值"></blog-post> <blog-post v-for="item in posts" v-bind:title="item.title"></blog-post> </div> <script> //定义一个组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你点一下我就加一,现在是:{{ count }}</button>' }); //定义一个可以传值的组件 Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }) new Vue({el:"#app", data:{ posts: [ { id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } } );<!--实例要写在组件定义之后--> </script> </body> </html>
注意事项:每个组件必须只有一个根元素,假如上面的模板(template)这样定义就会报错
Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3><h2>{{ title }}</h2>' })
解决的方法就是把所有的标签都放在同一个父标签中
Vue.component('blog-post', { props: ['title'], template: '<div><h3>{{ title }}</h3><h2>{{ title }}</h2></div>' })
重构一下组件了,让它变成接受一个单独的 post
prop
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> <!-- <blog-post title="这就是传过来的值"></blog-post> <blog-post v-for="item in posts" v-bind:title="item.title"></blog-post>--> <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" ></blog-post> </div> <script> //定义一个组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你点一下我就加一,现在是:{{ count }}</button>' }); //定义一个可以传值的组件 /*Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3><h2>{{ title }}</h2>' })*/ /* Vue.component('blog-post', { props: ['title'], template: '<div><h3>{{ title }}</h3><h2>{{ title }}</h2></div>' })*/ Vue.component('blog-post', { props: ['post'], template: "<div class='blog-post'><h3>{{ post.title }}</h3><div v-html='post.content'></div></div> " }) new Vue({el:"#app", data:{ posts: [ { id: 1, title: 'My journey with Vue',content:"第一个文章内容" }, { id: 2, title: 'Blogging with Vue',content:"第二个文章内容" }, { id: 3, title: 'Why Vue is so fun' ,content:"第三个文章内容"} ] } } );<!--实例要写在组件定义之后--> </script> </body> </html>
监听子组件事件
组件定义时绑定v-on:click='$emit(`enlarge-text`)'
组件使用时绑定v-on:enlarge-text="postFontSize += 0.1"
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="blog-posts-events-demo" > <div :style="{ fontSize: postFontSize + 'em' }"> <blog-post v-on:enlarge-text="postFontSize += 0.1" v-for="post in posts" v-bind:key="post.id" v-bind:post="post" ></blog-post> </div> </div> <script> Vue.component('blog-post', { props: ['post'], template: " <div class='blog-post'> <h3>{{ post.title }}</h3> <button v-on:click='$emit(`enlarge-text`)'> Enlarge text </button> <div v-html='post.content'></div></div>" }) new Vue({ el: '#blog-posts-events-demo', data: { posts: [ { id: 1, title: 'My journey with Vue',content:"第一个文章内容" }, { id: 2, title: 'Blogging with Vue',content:"第二个文章内容" }, { id: 3, title: 'Why Vue is so fun' ,content:"第三个文章内容"}], postFontSize: 1 } }) <!--实例要写在组件定义之后--> </script> </body> </html>
插槽
插槽的定义
Vue.component('alert-box', { template:"<div class='demo-alert-box'> <strong>Error!</strong> <slot></slot> </div>" })
<slot></slot>就的代表组件插入的位置
<alert-box> Something bad happened. </alert-box>
局部注册
上面所有使用Vue.component()方式注册的组件都是全局的,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="app"> <component-a></component-a> <component-b></component-b> </div> <div id="app1"> <component-a></component-a> <component-b></component-b> </div> <script> var ComponentA ={ template:"<strong>ComponentA!</strong>" }; var ComponentB ={ template:"<strong>ComponentB!</strong>" }; new Vue({ el: '#app', components: { 'component-a': ComponentA, 'component-b': ComponentB } }) </script> </body> </html>
上面的代码对中id为app1的div是无法使用那两个组件的,但也不会报错
注意局部注册的组件在其子组件中不可用。
var ComponentB ={ template:"<strong>ComponentB! <component-a></component-a></strong>" };
如果你想向上面一样在B组件里使用A组件,你需要这样写
var ComponentB ={ components:{ 'component-a': ComponentA }, template:"<strong>ComponentB! <component-a></component-a></strong>" };
prop
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->组件</title> </head> <body> <div id="app"> <blog-post title="静态传入" ></blog-post> <!-- 数值的传入需要使用v-bind进行绑定--> <blog-post v-bind:likes="123"></blog-post> <!--传递一个boolean isPublished要变为is-published--> <blog-post v-bind:is-published="true"></blog-post> <!--传递一个对象--> <blog-post v-bind:author="{ name: 'Veronica', company: 'Veridian Dynamics' }" ></blog-post> <!--传递一个数组--> <blog-post v-bind:comment-ids="[123, 456, 789]"></blog-post> <!-- 动态赋予一个变量的值 --> <div v-for="post in items"> <blog-post v-bind:title="post"></blog-post> </div> <!-- <blog-post v-bind:title="post.title + ' by ' + post.author.name"></blog-post>--> </div> <script> Vue.component('blog-post', { // 在 JavaScript 中是 camelCase 的 props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor }, template: '<h3>{{title}}--{{likes}}-->{{isPublished}}-->{{author}}-->{{commentIds}}</h3>' }) new Vue({ el: '#app', data:{ items:["天雁","孤欧","风鹤","血雕","斗鹰"] } }) </script> </body> </html>