博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue.js非常重要之组件
阅读量:6256 次
发布时间:2019-06-22

本文共 5665 字,大约阅读时间需要 18 分钟。

Vue.js的组件

注册组件

全局注册

要注册一个全局组件,你可以使用 Vue.component(tagName, options)。例如:

Vue.component('my-component', {  // 选项})

组件在注册之后,便可以在父实例的模块中以自定义元素 < my-component >< /my-component > 的形式使用。要确保在初始化根实例之前注册了组件:

// 注册组件Vue.component('my-component', {    template: '

hi girl

'})// 创建根实例new Vue({ el: '#box'})

结果

hi,girl

局部注册

不必在全局注册每个组件。通过使用组件实例选项注册,可以使组件仅在另一个实例/组件的作用域中可用:

var Child = {  template: '
A custom component!
'}new Vue({ // ... components: { 'my-component': Child }})

当我们感觉template里面写的东西太多了,我们还可以利用vue给我们提供的一个方法 x-template:

var Child = {  template: '#a'}

DOM 模板解析说明

当使用 DOM 作为模板时 (例如,将 el 选项挂载到一个已存在的元素上), 你会受到 HTML 的一些限制,因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模板内容。尤其像这些元素 < ul >,< ol >,< table >,< select > 限制了能被它包裹的元素,而一些像 < option > 这样的元素只能出现在某些其它元素内部。

在自定义组件中使用这些受限制的元素时会导致一些问题,例如:

...

自定义组件 <my-row> 被认为是无效的内容,因此在渲染的时候会导致错误。变通的方案是使用特殊的 is 属性:

data 必须是函数

通过 Vue 构造器传入的各种选项大多数都可以在组件里用。data 是一个例外,它必须是函数。实际上,如果你这么做:

Vue.component('my-component', {  template: '{
{ message }}
', data: { message: 'hello' }})

那么 Vue 会停止,并在控制台发出警告,告诉你在组件中 data 必须是一个函数。理解这种规则的存在意义很有帮助,让我们假设用如下方式来绕开 Vue 的警告:

var data = { counter: 0 }Vue.component('simple-counter', {  template: '',  // 技术上 data 的确是一个函数了,因此 Vue 不会警告,  // 但是我们返回给每个组件的实例却引用了同一个 data 对象  data: function () {    return data  }})new Vue({  el: '#example-2'})
0 0 0

由于这三个组件共享了同一个 data,因此增加一个 counter 会影响所有组件!这不对。我们可以通过为每个组件返回全新的 data 对象来解决这个问题:

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

现在每个 counter 都有它自己内部的状态了:

0 0 0

构成组件

组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。

在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。看看它们是怎么工作的。

使用 props 传递数据

如果我们定义了组件本身的属性时,我们需要 props 来注册属性,这样我们才能利用属性

Vue.component('mycom',{    template:"",    props:['a'],    metods:{        sss:function(){            alert(this.a)        }    }    })

结果

ddd

父元素向子元素传递数据

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,我们需要通过子组件的 props 选项。

Vue.component('mycom',{    template:"",    props:['a'],    methods:{        sss:function(){            alert(this.a)        }    }})new Vue({    el:'#box',    data:{        ddd:'hi'    }})

结果

hi

子元素向父元素传递数据

Vue.component('mycom',{    template:"",    props:['a'],    methods:{        sss:function(){            this.$emit('fff')        }    }})new Vue({    el:'#box',    data:{        ddd:'hi'    },    methods:{        gg:function(){            alert(111)        }    }})

结果

111

我们也可以在组件触发的函数上传入参数

Vue.component('mycom',{    template:"",    props:['a'],    methods:{        sss:function(){            this.$emit('fff','a','b')        }    }})new Vue({    el:'#box',    data:{        ddd:'hi'    },    methods:{        gg:function(x,y){            alert(x+y)        }    }})

结果

ab

非父子关系传入数据

有时候两个组件也需要通信 (非父子关系)。在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线:

var bus = new Vue()
// 触发组件 A 中的事件bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件bus.$on('id-selected', function (id) {  // ...})

camelCase vs. kebab-case

HTML 特性是不区分大小写的。所以,当使用的不是字符串模板,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名:

Vue.component('child', {  // camelCase in JavaScript  props: ['myMessage'],  template: '{
{ myMessage }}
'})

如果你使用字符串模板,则没有这些限制。

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
  1. 也可以是一个自定义构造器函数,使用 instanceof 检测。

当 prop 验证失败,Vue 会抛出警告 (如果使用的是开发版本)。注意 props 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无法使用。

slot 内容分发

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

注意两点:

< app > 组件不知道它会收到什么内容。这是由使用 < app > 的父组件决定的。
< app > 组件很可能有它自己的模板。
为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” 如果你熟悉 Angular)。Vue.js 实现了一个内容分发 API,参照了当前 Web 组件规范草案,使用特殊的 < slot > 元素作为原始内容的插槽。

单个 Slot

除非子组件模板包含至少一个 < slot > 插口,否则父组件的内容将会被丢弃。当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。

最初在 < slot > 标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。
假定 my-component 组件有下面模板:

我是子组件的标题

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

父组件模板:

我是父组件的标题

这是一些初始内容

这是更多的初始内容

渲染结果:

我是父组件的标题

我是子组件的标题

这是一些初始内容

这是更多的初始内容

具名 Slot

<slot> 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。
例如,假定我们有一个 app-layout 组件,它的模板为:

父组件模板:

这里可能是一个页面标题

主要内容的一个段落。

另一个主要段落。

这里有一些联系信息

渲染结果为:

这里可能是一个页面标题

主要内容的一个段落。

另一个主要段落。

这里有一些联系信息

在组合组件时,内容分发 API 是非常有用的机制。

转载地址:http://gqnsa.baihongyu.com/

你可能感兴趣的文章
4,gps信号与地图匹配算法
查看>>
python print的用法
查看>>
之字形打印矩阵
查看>>
我的世界之电脑mod小乌龟 —— 方位上的操作 lua函数集
查看>>
游戏方案
查看>>
在 Linux 下搭建 Git 服务器
查看>>
StackExchange.Redis Client(转载)
查看>>
Leetcode题目:Bulls and Cows
查看>>
bk. 2014.12.1
查看>>
CEOI2014 wall Spoiler
查看>>
UVA10391 ZOJ1825 Compound Words【SET+暴力】
查看>>
动态规划------Combination Sum IV
查看>>
[BZOJ2463][中山市选2009]谁能赢呢?
查看>>
iOS数据持久化存储之属性列表
查看>>
最后冲刺时间
查看>>
前端开发薪资之各地区对比(图文分析)
查看>>
jquery简单的大背景banner图片全屏切换
查看>>
java疑问
查看>>
JAVAEE 介绍
查看>>
视图和路由
查看>>