VUE复习笔记11(组件基础)

基本demo

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

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

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

new Vue({ el: '#components-demo' })

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

组件的复用

我们可以将组件进行任意次数的复用

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

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

组件的组织

通常一个应用会以一个嵌套的组件树的形式来组织。

例如,你可能会有页头,页脚,侧边栏等区域。
为了能够在模板中使用,这些组件必须先调用引入,然后再进行注册来让vue识别。这里有2种组件的注册类型:全局注册和局部注册

通过props向子组件传递数据

如果创建一个博文组件。问题是如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的。这也正是 prop 的由来。

props是你在组件上注册一些自定义的特性,当一个值传递给一个prop特性的时候,就变成了组件实例的一个属性。

<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>

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
//这里的{{title}}就获取了组件title属性穿过来到props中的值,再去props中获取
})

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

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

父组件
  <div id="app">
    <test :msg="childmsg" @parentevent="pevent"></test>
  </div>

<script>
import test from './components/test'
export default {
  name: 'App',
  data(){
    return{
      msg:'',
      childmsg:'这是传递给子组件的内容'
    }
  },

  methods:{
    pevent(){
      console.log('这是子组件沟通父组件调用的父组件事件')
    }
  },
  computed:{

  },
  components:{
    test
  }
}
</script>
子组件
<template>
    <div class="test">
        {{msg}}
        <p @click="tryclick">点击试试</p>
    </div>
</template>

<script>
    export default{
        props:['msg'],
        data(){
            return{

            }
        },
        created(){

        },
        methods:{
            tryclick(){
                this.$emit('parentevent');
            }
        }
    }
</script>
解释:

父组件中引用,声明,并且调用子组件,
然后在test子组件上,动态绑定 msgmsg的值为childmsgchildmsg的值在data中。
子组件中接收propsprops中接收msg属性,然后获得childmsg

单个根元素

组件必须包含一个根元素在最外层。否则会提示

通过事件向父级组件发送消息

我们开发组件的时候,可能要求组件和父级组件进行沟通。
由子组件向父组件沟通的事件为:emit
我们可以调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件:

还是以之前的代码的例子作解释:
子组件p标签绑定点击事件,点击事件中触发

this.$emit('parentevent','hello');
第一个参数为父组件的事件名,第二个为可选信息参数
<test :msg="childmsg" @parentevent="pevent"></test>

父组件中绑定改事件的方法名:@parentevent,然后在绑定父组件中的方法,调用pevent。
这样就实现了,子组件调用父组件方法的过程。

在组件上使用v-model

自定义事件也可以用于创建输入 v-model 自定义输入组件。

<input v-model="searchText">

等价于:
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

当在组件上使用 v-model时

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

通过插槽分发内容

和HTML元素一样,我经常需要向一个组件出阿尼的内容。

<alert-box>
  Something bad happened.
</alert-box>

然而直接在 组件的标签中写内容并不会生效,
vue中有一个自定义的 slot 元素可以解决这个问题。

父组件
  <div id="app">
    <test :msg="childmsg" @parentevent="pevent">1234567</test>
  </div>

子组件
    <div class="test">
        {{msg}}
        <p @click="tryclick">点击试试</p>
        <slot></slot>
    </div>

父组件中在组件标签内添加了文本,我们想要在子组件中的特定的地方显示出来。
只需要在子组件中使用<slot>标签即可。对应的内容会显示在<slot>标签内。这就是所谓的插槽。

到目前为止,关于插槽你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把插槽读完。

动态组件

有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里:


image.png

上述内容可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现:

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

其中绑定的变量 currentTabComponent 在通过计算属性更改就行了。
在上述示例中,currentTabComponent 可以包括

已注册组件的名字,或一个组件的选项对象

可以在这里查阅并体验完整的代码,或在这个版本了解绑定组件选项对象,而不是已注册组件名的示例。

到目前为止,关于动态组件你需要了解的大概就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把动态和异步组件读完。

解析dom模板时的注意事项

有些 HTML 元素,诸如<ul><ol><table><select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr><option>,只能出现在其它某些特定的元素内部。

因为如上的规则,会导致我们使用的时候有一些约束,
例如:

<table>
  <blog-post-row></blog-post-row>
</table>

这样肯定是不可行的。

这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:

<table>
  <tr is="blog-post-row"></tr>
</table>

遇到这情况,我们还是按规定写tr标签,带一个 is属性,把我们的组件名字当做值传入即可。这样也能够渲染组件的内容。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容