资讯专栏INFORMATION COLUMN

Vue.js非常重要之组件

ysl_unh / 3405人阅读

摘要:它们之间必然需要相互通信父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。父组件通过向下传递数据给子组件,子组件通过给父组件发送消息。这是由使用的父组件决定的。

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 > 这样的元素只能出现在某些其它元素内部。
在自定义组件中使用这些受限制的元素时会导致一些问题,例如:

...

自定义组件 被认为是无效的内容,因此在渲染的时候会导致错误。变通的方案是使用特殊的 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)
        }
    }
    })

结果

ffffd
父元素向子元素传递数据

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

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

结果

hi
子元素向父元素传递数据
Vue.component("mycom",{
    template:"",
    props:["a"],
    methods:{
        sss:function(){
            this.$emit("fff")
        }
    }
})
new Vue({
    el:"#box",
    data:{
        ffffd:"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:{
        ffffd:"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

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

元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。
仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。
例如,假定我们有一个 app-layout 组件,它的模板为:

父组件模板:


  

这里可能是一个页面标题

主要内容的一个段落。

另一个主要段落。

这里有一些联系信息

渲染结果为:

这里可能是一个页面标题

主要内容的一个段落。

另一个主要段落。

这里有一些联系信息

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88343.html

相关文章

  • 前端每周清单第 34 期:Vue 现状盘点与 3.0 展望,React 代码迁移与优化,图片优化详论

    摘要:工程实践立足实践,提示实际水平内联函数与性能很多关于性能优化的文章都会谈及内联函数,其也是常见的被诟病为拖慢性能表现的元凶之一不过本文却是打破砂锅问到底,论证了内联函数并不一定就会拖慢性能,过度的性能优化反而会有损于应用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...

    CoderStudy 评论0 收藏0
  • Vue面试题精选:Vue与React的区别,分别在哪些场景下使用更合适?

    摘要:它们是高度重视且广泛使用的框架,用于界面设计。应用程序开发引起了全球开发人员的极大关注,以构建令人惊叹的应用程序。但是,具有适应性强的体系结构,使其成为广泛使用的框架之一,具有最新的库和包。专业和出色的社区支持,以解决任何问题。 JavaScript是世界上最流行的语言之一,React和Vue是JS最流行的两个框架。但哪一款最适合你? JavaScript越来越受欢迎,许多科技巨头正在...

    mcterry 评论0 收藏0
  • Vue面试题精选:Vue与React的区别,分别在哪些场景下使用更合适?

    摘要:它们是高度重视且广泛使用的框架,用于界面设计。应用程序开发引起了全球开发人员的极大关注,以构建令人惊叹的应用程序。但是,具有适应性强的体系结构,使其成为广泛使用的框架之一,具有最新的库和包。专业和出色的社区支持,以解决任何问题。 JavaScript是世界上最流行的语言之一,React和Vue是JS最流行的两个框架。但哪一款最适合你? JavaScript越来越受欢迎,许多科技巨头正在...

    lijy91 评论0 收藏0
  • Vue ES6 Jade Scss Webpack Gulp

    摘要:主有前端后端,并加,各一名。本着工欲善其事,必先利其器的理念,一直以来在工作效率这块,略怀执念一个问题不应该被解决两次。下图为开发项目机制所涉及到的插件工欲善其事,必先利其器,语言,框架皆可以归结为器而不当仅局限于开发工具以及机。 原文链接: http://www.jeffjade.com/2016/05/08/106-vue-es6-jade-scss-webpack-gulp/ 一...

    rickchen 评论0 收藏0

发表评论

0条评论

ysl_unh

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<