第十一课时: 关于Vue组件一些注意的地方

栏目: 编程语言 · 发布时间: 4年前

内容简介:1.注册组件就是利用Vue.component()方法2.可以理解为一个vue文件就是一个组件组件的模板中只能有一个根元素

组件的基本使用

注册组件

1.注册组件就是利用Vue.component()方法

2.可以理解为一个vue文件就是一个组件

模板要求

组件的模板中只能有一个根元素

组件中的data必须是函数

var app = new Vue({
    data () {
      return {
        message: 'hello world'
      }
    }
})

组件的属性和事件

例,一个父组件:

<my-component v-bind:foo="baz" v-on:event-a="doThis(arg1,...arg2)"></my-component>

上面代码

  • foo<my-component> 组件内部定义的一个 prop 属性, baz 是父组件的一个data属性,
  • event-a 是子组件定义的一个事件, doThis 是父组件的一个方法

执行过程应该是这样的:

  • 父组件把 baz 数据通过 prop 传递给子组件的 foo
  • 子组件内部得到 foo 的值,就可以进行相应的操作;
  • 当子组件内部发生了一些变化,希望父组件能知道时,就利用代码触发 event-a 事件,把一些数据发送出去
  • 父组件把这个事件处理器绑定为 doThis 方法,子组件发送的数据,就作为 doThis 方法的参数被传进来
  • 然后父组件就可以根据这些数据,进行相应的操作

属性Props

Vue组件通过 props 属性来声明一个自己的属性,然后父组件就可以往里面传递数据。

Vue.component('mycomponent',{
    template: '<div>这是一个自定义组件,父组件传给我的内容是:{{myMessage}}</div>',
    props: ['myMessage'],
    data () {
      return {
        message: 'hello world'
      }
    }
  })

然后调用该组件

<div id="app">
    <mycomponent my-message="hello"></mycomponent>
</div>

注意,由于HTML特性是不区分大小写的,所以传递属性值时, myMessage 应该转换成 kebab-case (短横线隔开式) my-message="hello"

v-bind绑定属性值

<div attr="message">hello</div>

上面这样, div 元素的 attr 特性值就是 message 。而这样

<div v-bind:attr="message">hello</div>

这里的 message 应该是Vue实例的data的一个属性,这样 div 元素的 attr 特性值就是 message 这个属性的值。

之所以说是一般情况,是因为 classstyle 特性并不是这样。用 v-bind:classclass 传入正常的类名,效果是一样的,因为对于这两个特性,Vue采用了合并而不是替换的原则。

子组件希望对传入的prop进行操作

根据上面,想要把父组件的属性绑定到子组件,应该使用 v-bind ,这样,父组件中数据改变时能反映到子组件。

注意在子组件中最好不要更改父组件传入的值,如果非要更改的话,加上 .sync 修饰符

例父组件

<my-component :child-array.sync="parentArray"></my-component>

子组件

methods: {
     changeArray () {
       this.counter++
       this.$emit('update:childArray', this.counter)
     }
}

给子组件传递正确类型的值

同样是上面的原因,静态的给子组件的特性传递值,它都会把他当做一个字符串。

<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp>

子组件中,特性的值是字符串 "1" 而不是 number 1。如果想传递正确的数值,应该使用v-bind传递,这样就能把传递的值当做一个表达式来处理,而不是字符串。

<!-- 传递实际的 number 1 -->
<comp v-bind:some-prop="1"></comp>

Prop验证

我们可以给组件的 props 属性添加验证,当传入的数据不符合要求时,Vue会发出警告。

Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    propA: Number,
    // 多种类型
    propB: [String, Number],
    // 必传且是字符串
    propC: {
      type: String,
      required: true
    },
    // 数字,有默认值
    propD: {
      type: Number,
      default: 100
    },
    // 数组/对象的默认值应当由一个工厂函数返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

type 可以是下面原生构造器:

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

type 也可以是一个自定义构造器函数

自定义事件

通过prop属性,父组件可以向子组件传递数据,而自定义事件就是用来将子组件的内部数据报告给父组件的。

<div id="app3">
    <my-component2 v-on:myclick="onClick"></my-component2>
</div>
<script>
  Vue.component('my-component2', {
    template: `<div>
    <button type="button" @click="childClick">点击我触发自定义事件</button>
    </div>`,
    methods: {
      childClick () {
        this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
      }
    }
  })
  new Vue({
    el: '#app3',
    methods: {
      onClick () {
        console.log(arguments)
      }
    }
  })
</script>

如上所示,共分为以下步骤:

  1. 子组件在自己的方法中将自定义事件以及需要发出的数据通过以下代码发送出去

    this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
    第一个参数是自定义事件的名字
    后面的参数是依次想要发送出去的数据
  2. 父组件利用 v-on 为事件绑定处理器

    <my-component2 v-on:myclick="onClick"></my-component2>

    这样,在Vue实例的 methods 方法中就可以调用传进来的参数了

注意: 在使用 v-on 绑定事件处理方法时,不应该传进任何参数,而是直接写 v-on:myclick="onClick" ,不然,子组件暴露出来的数据就无法获取到了

绑定原生事件

如果想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on

探究 v-model

v-model 可以对表单控件实现数据的双向绑定,它的原理就是利用了绑定属性和事件来实现的。比如 input 控件。不使用 v-model ,可以这样实现数据的双向绑定:

<div id="app4">
    <input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)">
    {{text}}
</div>
<script>
  new Vue({
    el: '#app4',
    data: {
      text: '444'
    },
    methods: {
      changeValue (value) {
        this.text = value
      }
    }
  })
</script>

上面的代码同样实现了数据的双向绑定。其本质就是:

  • inputvalue 特性绑定到Vue实例的属性 text 上, text 改变, input 中的内容也会改变
  • 然后把表单的 input 事件处理函数设置为Vue实例的一个方法,这个方法会根据输入参数改变Vue中 text 的值
  • 相应的,在 input 中输入内容时,触发了 input 事件,把 event.target.value 传给这个方法,最后就实现了改变绑定的数据的效果。

v-model 就是上面这种方式的语法糖,也就是把上面的写法封装了一下,方便我们使用。

使用slot分发内容

单个slot

上面用到的很多组件的使用方式是这样的:

<component></component>

也就是说组件中是空的,没有放置任何文本或元素。但是原生的html元素都是可以进行嵌套的, div 里面放 table 什么的。自定义组件开闭标签之间也可以放置内容,不过需要在定义组件时使用 slot

slot 相当于子组件设置了一个地方,如果在调用它的时候,往它的开闭标签之间放了东西,那么它就把这些东西放到 slot 中。

  1. 当子组件中没有slot时,父组件放在子组件标签内的东西将被丢弃;
  2. 子组件的slot标签内可以放置内容,当父组件没有放置内容在子组件标签内时,slot中的内容会渲染出来;
  3. 当父组件在子组件标签内放置了内容时,slot中的内容被丢弃

子组件的模板:

<div>
  <h2>我是子组件的标题</h2>
  <slot>
    只有在没有要分发的内容时才会显示。
  </slot>
</div>

父组件模板:

<div>
  <h1>我是父组件的标题</h1>
  <my-component>
    <p>这是一些初始内容</p>
  </my-component>
</div>

渲染结果:

<div>
  <h1>我是父组件的标题</h1>
  <div>
    <h2>我是子组件的标题</h2>
    <p>这是一些初始内容</p>
  </div>
</div>

具名slot

slot 可以有很多个。那么子组件对于父组件放置的多余的内容如何放到各个 slot 中呢?方法就是子组件给每个 slot 起一个名字 name ,父组件放置多余的元素时,给每个元素的 slot 属性分配一个代表 slot 的名字。到时候,多余的内容就会根据自己的 slot 属性去找具有对应名字的 slot 元素。

注意:

  1. 子组件可以有一个匿名的slot,当分发的多余内容找不到对应的slot时,就会进入这里面
  2. 如果子组件没有匿名的slot,当分发的多余内容找不到对应的slot时,就会被丢弃

例如,假定我们有一个 app-layout 组件,它的模板为:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

父组件模版:

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

作用域插槽

作用域插槽也是一个插槽 slot ,但是他可以把数据传递给到父组件的特定元素内,然后有父组件决定如何渲染这些数据。

  1. 首先,子组件的 slot 需要有一些特性(prop)

    Vue.component('my-component4', {
         template: `<div>
           <slot :text="hello" message="world"></slot>
         </div>`,
         data () {
           return {
             hello: [1,'2']
           }
         }
       })
  2. 父组件在调用子组件时,需要在里面添加一个 template 元素,并且这个 template 元素具有 scope 特性

    <div id="app7">
      <my-component4>
        <template scope="props">
        </template>
      </my-component4>
     </div>

    scope 特性的值,就代表了所有子组件传过来的数据组成的对象。相当于

    props = {
        text: '',
       message: ''
    }
  3. 最后,父组件就可以在 template 中渲染子组件传过来的数据了

    <div id="app7">
       <my-component4>
         <template slot-scope="props">
           <span>{{props.text}}</span>
           <span>{{props.message}}</span>
         </template>
       </my-component4>
      </div>

    作用域插槽也是插槽,只不过是多加了些特性,然后父组件多进行了些处理。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

WebKit技术内幕

WebKit技术内幕

朱永盛 / 电子工业出版社 / 2014-6 / 79.00元

《WebKit技术内幕》从炙手可热的HTML5 的基础知识入手,重点阐述目前应用最广的渲染引擎项目——WebKit。不仅着眼于系统描述WebKit 内部渲染HTML 网页的原理,并基于Chromium 的实现,阐明渲染引擎如何高效地利用硬件和最新技术,而且试图通过对原理的剖析,向读者传授实现高性能Web 前端开发所需的宝贵经验。 《WebKit技术内幕》首先从总体上描述WebKit 架构和组......一起来看看 《WebKit技术内幕》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试