组件是什么
组件是带有名称的可复用实例。
组件可以扩展 HTML 元素,封装可重用的代码。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
在这里插入图片描述
这里有一个 Vue 组件的示例,在下面的例子中我们设置一个组件,其名为 <button-counter>
。我们可以把这个组件作为一个根实例中的自定义元素来使用:
<body> <div id="components-demo"> <button-counter></button-counter> </div> <script> // Create a Vue application const app = Vue.createApp({}) // Define a new global component called button-counter app.component('button-counter', { data() { return { count: 0 } }, template: ` <button v-on:click="count++"> You clicked me {{ count }} times. </button>` }) app.mount('#components-demo') </script> </body>
(注意:其中,template 中 ` 是反引号,不是单单引号 '。)
组件是可复用的实例,它们与根实例接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等
可以将组件进行任意次数的复用,且复用的组件之间互不影响,每复用一次组件,则新建一个实例。
如将components-demo中组件多次复用,每个组件各自维护自己的counter,互不影响。
<div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div>
在这里插入图片描述
组件的data 选项和method选项
组件的 data 是一个函数。Vue 会在创建新组件实例的过程中调用此函数。
可以理解为data是组件专门用于存放数据的。Vue仅仅会在首次创建中调用这个函数,所以需要确保它们都在 data 函数返回的对象中。
<body> <div id="app" class="demo"></div> <script> const app = Vue.createApp({ data() { return { count: 4 } } }) const vm = app.mount('#app') document.write(vm.$data.count) // => 4 document.write("<br>") document.write(vm.count) // => 4 document.write("<br>") // 修改 vm.count 的值也会更新 $data.count vm.count = 5 document.write(vm.$data.count) // => 5 document.write("<br>") // 反之亦然 vm.$data.count = 6 document.write(vm.count) // => 6 </script> </body>
组件的 methods 选项包含了所需方法的对象,Vue 自动为 methods 绑定 this,以便于它始终指向组件实例。
<body> <div id="app" class="demo"></div> <script> const app = Vue.createApp({ data() { return { count: 4 } }, methods: { increment() { // `this` 指向该组件实例 this.count++ } } }) const vm = app.mount('#app') document.write(vm.count) // => 4 document.write("<br>") vm.increment() document.write(vm.count) // => 5 </script> </body>
这些 methods 和组件实例的其它所有 property 一样可以在组件的模板中被访问。在模板中,它们通常被当做事件监听使用,比如
<body> <div id="increment-test" class="demo"> {{count}} <button @click="increment">Up vote</button> </div> <script> const app = Vue.createApp({ data() { return { count: 4 } }, methods: { increment() { // `this` 指向该组件实例 this.count++ } } }) const vm = app.mount('#increment-test') document.write(vm.count) // => 4 document.write("<br>") vm.increment() document.write(vm.count) // => 5 </script> </body> </html>
在这里插入图片描述
组件的组织
在实际应用中,一个页面可能会分为页头,侧边栏,内容栏,底部栏等组件,为了能在模板中使用,这些组件必须先注册以便Vue能够识别他们。这里有两种组件的注册类型:全局注册和局部注册。
全局注册
以上的实例就是通过 component 全局注册,全局注册的组件可以在随后创建的 app 实例模板中使用,也包括根实例组件树中的所有子组件的模板中。
app.component('button-counter', { data() { return { count: 0 } }, template: ` <button v-on:click="count++"> You clicked me {{ count }} times. </button>` })
其组件名为 app.component 的第一个参数,在上面的例子中,组件的名称是“button-counter”
局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用其中一个组件了,它仍然会被包含在最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
可以通过一个普通的 JavaScript 对象来定义组件
const ComponentA = { /* ... */ } const ComponentB = { /* ... */ }
然后在 components 选项中定义你想要使用的组件:
const app = Vue.createApp({ components: { 'component-a': ComponentA, 'component-b': ComponentB } })
下面实例注册了子组件A和子组件B,然后利用父组件使用这两个组件。
<body> <div id="component-test"></component> <runoob-a></runoob-a> <runoob-b></runoob-b> </div> <script> var runoobA = { template: '<h1>我是子组件A!</h1>' } var runoobB = { template: '<h1>我是子组件B!</h1>' } const app = Vue.createApp({ components: { 'runoob-a': runoobA, 'runoob-b': runoobB } }) app.mount('#component-test') </script> </body>
在这里插入图片描述
组件的Prop
如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的。这也正是 prop 的由来。
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
Prop 是你可以在组件上注册的一些自定义 attribute。为了给博文组件传递一个标题,我们可以用 props 选项将其包含在该组件可接受的 prop 列表中:
<body> <div id="blog-post-demo" class="demo"> <blog-post title="My journey with Vue"></blog-post> <blog-post title="Blogging with Vue"></blog-post> <blog-post title="Why Vue is so fun"></blog-post> </div> <script> const app = Vue.createApp({}) app.component('blog-post', { props: ['title'], template: `<h4>{{ title }}</h4>` }) app.mount('#blog-post-demo') </script>
每个 prop 都可以有指定的值类型,可以以对象形式列出 prop,这些 property 的名称和值分别是 prop 各自的名称和类型
<body> <div id="site-test"> <site-info v-for="site in sites" :id="site.id" :title="site.title" ></site-info> </div> <script> const Site = { data() { return { sites: [ { id: 1, title: 'Google' }, { id: 2, title: 'Runoob' }, { id: 3, title: 'Taobao' } ] } } } const app = Vue.createApp(Site) app.component('site-info', { props: ['id','title'], template: `<h4>{{ id }} - {{ title }}</h4>` }) app.mount('#site-test') </script> </body>
其他有关prop的内容请阅读官方文档:Props