vue 组件

介绍

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:
在这里插入图片描述
在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。在 Vue 中注册组件很简单:

		<div id="app">
			<todo-item></todo-item>
			<todo-item></todo-item><!-- 可重复调用 -->
		</div>
		<script type="text/javascript">
			Vue.component('todo-item',{
				template:'<p>一个p标签模板</p>'
			})
			new Vue({
				el:"#app", 
				data:{	
					
				},
			})
		</script>

但是这样会为每个待办项渲染同样的文本,这看起来并不炫酷。我们应该能从父作用域将数据传到子组件才对。让我们来修改一下组件的定义,使之能够接受一个 prop:

<div id="app">
			<ol>
			<todo-item v-for="item in list" v-bind:todo="item" :key="item.id">
				<!-- 现在我们为每个 todo-item 提供 todo 对象, todo 对象是变量,即其内容可以是动态的。
				v-for 遍历 list
				v-bind绑定todo属性 值为遍历的item
				-->
			</todo-item>
			</ol>
		</div>
		<script type="text/javascript">
			//todo-item  是创建的模板名
			Vue.component('todo-item',{
				// todo-item 组件现在接受一个
				// "prop",类似于一个自定义 attribute。
				// 这个 prop 名为 todo。
				props:['todo'] ,  //类似于给 todo-item 加一个名为todo 的属性  
				template:'<li>{{todo.text}}</li>'  //{{todo.text}}  list里的值
			})
			var app = new Vue({
				el:"#app", 
				data:{	
					list:[
						{id:0,text:"蔬菜"},
						{id:1,text:"水果"},
						{id:2,text:"其他随便什么人吃的东西"}
					]
				},
			})
		</script>

组件基础

基本示例


这里有一个 Vue 组件的示例:

<div id="app">
			<button-counter></button-counter>
		</div>
		<script type="text/javascript">
			Vue.component('button-counter',{
				data:function(){
					return {
						count:0,
					}
				},
				template:'<button v-on:click="count++">你点击了我 {{count}} 次</button>'
			})
			new Vue({
				el:"#app", 
				data:{	
					
				},
			})
		</script>

组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用:

  • 因为组件是可复用的 Vue 实例,所以它们与 new Vue接收相同的选项,例如 datacomputedwatchmethods以及生命周期钩子等。仅有的例外是像el这样根实例特有的选项。

组件的复用


你可以将组件进行任意次数的复用:

<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

可以利用之前的例子测试。。。

  • 关于复用:当点击按钮时,每个组件都会各自独立维护它的count。因为你每用一次组件,就会有一个它的新实例被创建。

# data必须是一个函数

当我们定义这个 <button-counter>组件时,你可能会发现它的 data并不是像这样直接提供一个对象:

data: {
  count: 0
}

取而代之的是,一个组件的 data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

如果 Vue 没有这条规则,点击一个按钮就可能会影响到其它所有实例

组建的组织


通常一个应用会以一棵嵌套的组件树的形式来组织:如博客开头的图片。。。

例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:

Vue.component('my-component-name', {
  // ... options ...
})

全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

通过 Prop 向子组件传递数据


Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:


		<script type="text/javascript">
			Vue.component('blog-post',{
				props:['title'],
				template:'<p>{{title}}</p>'
			})
			new Vue({
				el:"#app", 
				data:{	
					
				},
			})
		</script>

一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data中的值一样。

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来

<div id="app">
			<blog-post title="曾经沧海难为水,"></blog-post>
			<blog-post title="除却巫山不是云。"></blog-post>
			<blog-post title="取次花丛懒回顾,"></blog-post>
			<blog-post title="半缘修道半缘君。"></blog-post>
</div>

然而在一个典型的应用中,你可能在 data里有一个博文的数组:

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

并想要为每篇博文渲染一个组件:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>

如上所示,你会发现我们可以使用 v-bind 来动态传递 prop。这在你一开始不清楚要渲染的具体内容,比如从一个 API 获取博文列表的时候,是非常有用的。

单个根元素


当构建一个 组件时,你的模板最终会包含的东西远不止一个标题:
<h3>{{ title }}</h3>

最最起码,你会包含这篇博文的正文:

<h3>{{ title }}</h3>
<div v-html="content"></div>

然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:

<div class="blog-post">
  <h3>{{ title }}</h3>
  <div v-html="content"></div>
</div>

看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
  v-bind:content="post.content"
  v-bind:publishedAt="post.publishedAt"
  v-bind:comments="post.comments"
></blog-post>

所以是时候重构一下这个 组件了,让它变成接受一个单独的 post prop:

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <div v-html="post.content"></div>
    </div>
  `
})

现在,不论何时为post对象添加一个新的 property,它都会自动地在 <blog-post>内可用。

监听子组件事件及后续内容,请关注博主后续博客。。。。。。

  • 20
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值