美文网首页从0到1_前端开发
Web App开发--Vue组件化应用构建

Web App开发--Vue组件化应用构建

作者: ef43ffb32440 | 来源:发表于2017-05-08 16:06 被阅读333次

什么是组件?


组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

组件化应用构建


组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、自包含和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:


使用组件


# 全局注册

之前说过,我们可以通过以下方式创建一个 Vue 实例:

new Vue({
  el: '#some-element',
  // 选项
})

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

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

对于自定义标签名,Vue.js 不强制要求遵循 W3C规则 (小写,并且包含一个短杠),尽管遵循这个规则比较好。

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

<div id="example">
  <my-component></my-component>
</div>
// 注册
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
// 创建根实例
new Vue({
  el: '#example'
})

渲染为:

<div id="example">
  <div>A custom component!</div>
</div>
# 局部注册

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

var Child = {
  template: '<div>A custom component!</div>'
}
new Vue({
  // ...
  components: {
    // <my-component> 将只在父模板可用,不添加到components选项里面则可适用于任何作用域
    'my-component': Child
  }
})

组件构造器选项


在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。因此,通过Vue构造器传入的各种选项大多数都可以在组件里用。 data 是一个例外,它必须是函数。
Vue组件构造器常用的选项:

// 注册
Vue.component('my-component', {
    template: '<div>A custom component!</div>', 
    data: function() {
        return {
            var1: xxx,
            var2: xxx
        }
    },
    computed: {
        sumOfVar2: function() {
            return (this.var2.innerVar1 + this.var2.innerVar2 + this.var2.innerVar3);
        }
    },
    watch: {
        'var1': function() {
        },
        'var2.innerVar1': function() {          
        },
        'var2.innerVar2': function() {  
        },
        'var2.innerVar3': function() {  
        }   
    },
    methods: {
        func1: function() {
        },
        func2: function() {
        },
        func3: function() {
        }
    },
    beforeCreate: function () {
    },
    created: function () {
    },
    beforeMount: function () {
    },
    mounted: function() {
    },
    beforeUpdate: function () {
    },
    updated: function () {
    },
    beforeDestroy: function() {
    },
    destroyed: function() {
    }
});

异步组件


在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载。为了让事情更简单, Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义。Vue.js 只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。

例如:

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // Pass the component definition to the resolve callback
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

工厂函数接收一个** resolve 回调**,在收到从服务器下载的组件定义时调用。也可以调用 reject(reason) 指示加载失败。这里 setTimeout 只是为了演示。怎么获取组件完全由你决定。

由于我们的项目没有用到Webpack等模块化构建工具,所以无法结合Webpack 的代码分割功能使用:

Vue.component('async-webpack-example', function (resolve) {
  // 这个特殊的 require 语法告诉 webpack
  // 自动将编译后的代码分割成不同的块,
  // 这些块将通过 Ajax 请求自动下载。
  require(['./my-async-component'], resolve)
})

但我们可以将各个组件的template代码单独写到一个html文件,通过Ajax的get方法获取组件html文件的内容,一样可以实现代码切割的功能,方便模块化管理代码:

Vue.component('my-component', function (resolve, reject) {
    $.get('url', function (text) {
        resolve({
            template: text,
            // 选项
        });
    });
});

局部组件


局部组件一般是在创建子组件的情况出现。生命周期依赖于父组件。
创建局部组件很简单:

const subComponent = {
    template: 'I am subComponent',
    data: function() {
        return {
            var: xxx
        }
    }
    methods: {
        back: function () {
            this.$router.back();
        },
    },
    // 其它选项
}

其它构造器选项和Vue实例、全局组件的构造器选项一样。

动态组件


通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换:

var vm = new Vue({
  el: '#example',
  data: {
    currentView: 'home'
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})
<component v-bind:is="currentView">
  <!-- 组件在 vm.currentview 变化时改变! -->
</component>

** # keep-alive **
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数:

<keep-alive>
  <component :is="currentView">
    <!-- 非活动组件将被缓存! -->
  </component>
</keep-alive>

API 参考查看更多 <keep-alive>的细节。

组件间通信


组件间通信,分为数据传递和事件分发两种情况。由于这一节很重要,所以单独开一章讲Vue组件间通信及Vuex状态管理模式

使用Slot分发内容


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

<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

注意两点:

  1. <app> 组件不知道它的挂载点会有什么内容。挂载点的内容是由<app>的父组件决定的。
  2. <app> 组件很可能有它自己的模版。

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

** # 编译作用域 **
在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译。假定模板为:

<child-component>
  {{ message }}
</child-component>

message 应该绑定到父组件的数据,还是绑定到子组件的数据?答案是父组件。组件作用域简单地说是:
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
一个常见错误是试图在父组件模板内将一个指令绑定到子组件的属性/方法:

<!-- 无效 -->
<child-component v-show="someChildProperty"></child-component>

假定 someChildProperty 是子组件的属性,上例不会如预期那样工作。父组件模板不应该知道子组件的状态。
如果要绑定作用域内的指令到一个组件的根节点,你应当在组件自己的模板上做:

Vue.component('child-component', {
  // 有效,因为是在正确的作用域内
  template: '<div v-show="someChildProperty">Child</div>',
  data: function () {
    return {
      someChildProperty: true
    }
  }
})

类似地,分发内容是在父作用域内编译。

** # 单个 Slot **

除非子组件模板包含至少一个 <slot> 插口,否则父组件的内容将会被丢弃。当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。
最初在 <slot> 标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

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

** 具名Slot **

<slot> 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。
仍然可以有一个匿名 slot ,它是默认 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>

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

上一篇: Web App开发--Vue生命周期与生命钩子
下一篇: Web App开发--Vue组件间通信

相关文章

  • Web App开发--Vue组件化应用构建

    什么是组件? 组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重...

  • vue 组件开发

    vue 提供了组件开发模型,使开发大中型web应用更加的方便。 vue的组件的概念包括components、tem...

  • Vue学习笔记2

    组件化应用构建 Vue实例 创建一个Vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实...

  • Vue基础(上)

    #### vue note --- 1、vue.js是什么? ​ 构建数据驱动的web应用开发框架 2、为什么如此...

  • 前端组件化开发

    组件化产生背景,为什么要组件化开发? web应用日趋复杂,传统开发成本高;随着网络普及web应用得到了迅速的发展。...

  • Vue-基础语法(三)

    组件化开发 一、组件概念组件化规范:Web Components 浏览器支持不好,vue 实现了这个规范https...

  • 01Vue组件化实战

    01 组件化实战 组件化 vue组件系统提供了⼀种抽象,让我们可以使用独立可复用的组件来构建大型应用,任意类型的应...

  • vue写调色板

    组件开发App.vue

  • vue组件化的好处及vue常见面试题

    1,组件化开发思想: 2, vue优点 vue是一个构建数据驱动的web界面的渐进式MVVM框架,性能好、简单易用...

  • 前端学习:《Vue.js快跑》中英文PDF+《Vue.js项目实

    《Vue.js快跑:构建触手可及的高性能Web应用》是用Vue.js构建Web应用的全方位指南。作者运用细致入微的...

网友评论

    本文标题:Web App开发--Vue组件化应用构建

    本文链接:https://www.haomeiwen.com/subject/gximtxtx.html