《风尚坐火箭学习vue》-- 第十三章:Vue中的组件(难点)

前言:前端框架千千万,独有vue占一半


我是风尚,让我们一起坐火箭去学习Vue

 


                                第十三章:Vue中的组件(难点)

上章回顾: 今天的Vue中的动画transition就讲到这里啊。 


“好家伙,牛,这动画可以,不就是记几个类名?继续”风尚嘚瑟的说。

“可以啊小伙子,来吧,整个难点的,Vue中的组件!!!”老头大声的说。

“来吧来吧”风尚说


Vue.js 组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

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

全局组件

 

// 注册

Vue.component('my-component', {

  template: '<div>一个自定义组件</div>'

})

// 创建根实例

new Vue({

  el: '#app'

})

// 模板

<div id="app">

  <my-component></my-component>

</div>

这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中

局部注册

局部注册

var Child = {

  template: '<div>一个自定义组件</div>'

}

new Vue({

  // ...

  components: {

    // <my-child></my-child> 将只在父组件模板中可用

    'my-child': Child

  }

})

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

var counter = {

  template:`<button @click="num++">{{num}}</button>`,

  data:function(){return {num:1}}

}

new Vue({

  el:"#app",     

  components:{

    counter,

  }

})

组件调用

<div id="app">

<counter></counter>

<counter></counter>

<counter></counter>

</div>

组件传参

当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。

<child message="hello!"></child>



Vue.component('child', {

  // 声明 props

  props: ['message'],

  // 就像 data 一样,prop 也可以在模板中使用

  // 同样也可以在 vm 实例中通过 this.message 来使用

  template: '<span>{{ message }}</span>'

})

动态 Prop

你也知道 prop 可以通过 v-bind 动态赋值

<div>

  <input v-model="parentMsg">

  <br>

  <child :my-message="parentMsg"></child>

</div>

如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 v-bind

todo: {

  text: '学习Vue',

  isComplete: false

}

<todo-item v-bind="todo"></todo-item>

=

<todo-item v-bind:text="todo.text" v-bind:is-complete="todo.isComplete"></todo-item>

单向绑定

Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会 另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop

在两种情况下,我们很容易忍不住想去修改 prop 中数据:

  1. Prop 作为初始值传入后,子组件想把它当作局部数据来用;
  2. Prop 作为原始数据传入,由子组件处理成其它数据输出。

1. 定义一个局部变量,并用 prop 的值初始化它:

props: ['initialCounter'],

data: function () {

  return { counter: this.initialCounter }

}

2. 定义一个计算属性,处理 prop 的值并返回:

  props: ['size'],

computed: {

  normalizedSize: function () {

    return this.size.trim().toLowerCase()

  }

}

验证

们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。这对于开发给他人使用的组件非常有用。

Vue.component('example', {

  props: {

    // 基础类型检测 (`null` 指允许任何类型)

    propA: Number,

    // 可能是多种类型

    propB: [String, Number],

    // 必传且是字符串

    propC: {

      type: String,

      required: true

    },

    // 数值且有默认值

    propD: {

      type: Number,

      default: 100

    },

type 可以是下列原生构造函数中的一个:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

子组件怎么跟父组件通信

我们知道,父组件使用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。
每个 Vue 实例都实现了事件接口,即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

<div id="app">

  <p>{{ total }}</p>

  <counter v-on:add="addTotal"></counter>

  <counter v-on:add="iaddTotal"></counter>

</div>

Vue.component('counter', {

  template: '<button v-on:click="addCounter">{{ counter }}</button>',

  data: function () {

    return {

      counter: 0

    }

  },

  methods: {

    addCounter: function () {

      this.counter += 1

      this.$emit('add')

    }

  },

})

new Vue({

  el: '#counter-event-example',

  data: {

    total: 0

  },

  methods: {

    addTotal: function () {

      this.total += 1

    }

  }

})

slot 插槽

在使用组件时,我们常常要像这样组合它们:

<app>

  <app-header></app-header>

  <app-footer></app-footer>

</app>

单个插槽

假定 my-component 组件有如下模板:

<div>

  <h2>我是子组件的标题</h2>

  <slot>

    只有在没有要分发的内容时才会显示。

  </slot>

</div>

父组件模板

<div>

  <h1>我是父组件的标题</h1>

  <my-component>

    <p>这是一些初始内容</p>

    <p>这是更多的初始内容</p>

  </my-component>

</div>

结果

<div>

  <h1>我是父组件的标题</h1>

  <div>

    <h2>我是子组件的标题</h2>

    <p>这是一些初始内容</p>

    <p>这是更多的初始内容</p>

  </div>

</div>

具名插槽

有时我们需要多个插槽。例如,假定我们有一个 app-layout 组件:

<div class="container">

  <header>

    <slot name="header"></slot>

  </header>

  <main>

    <slot></slot>

  </main>

  <footer>

    <slot name="footer"></slot>

  </footer>

</div>

slot 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

父组件模板

<app-layout>

  <h1 slot="header">这里可能是一个页面标题</h1>

  <p>主要内容的一个段落。</p>

  <p>另一个主要段落。</p>

  <p slot="footer">这里有一些联系信息</p>

</app-layout>

结果为:

<div class="container">

  <header>

    <h1>这里可能是一个页面标题</h1>

  </header>

  <main>

    <p>主要内容的一个段落。</p>

    <p>另一个主要段落。</p>

  </main>

  <footer>

    <p>这里有一些联系信息</p>

  </footer>

</div>

一个不带 name 的 出口会带有隐含的名字“default”。


“组件讲完了,风尚感觉如何?”老头说。

“啊?发生了啥?”风尚懵了.....

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风尚云网

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值