一定要牢记的几个 Vue 组件知识点

一开始,Vue 在其官方文档就说明了,Vue 组件都是 Vue 的实例。但由于我们使用 Vue 做项目时基本都是基于 *.vue 文件,全程也没有使用 new 去创建过实例,对Vue 组件都是 Vue 实例这句话并没有很直观的理解,也就谈不上什么深刻理解了。最近因项目原因复习了一遍 Vue 知识。本文记录个人觉得必须要牢记的 Vue 组件知识点。

vue-cmp

煎蛋栗子

<div id="app">
  {{ message }}
</div>

<script src="https://unpkg.com/vue"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue!'
    }
  })
</script>

虽然这个例子很简单,但却说明了 Vue 核心的工作原理:创建一个 Vue 实例,并与页面 DOM 建立绑定,当组件内部状态改变时,DOM 会自发地更新。在这个例子中,我们看到了我们熟悉的 new 关键词,总算可以勉强相信 Vue 组件都是 Vue 实例这句话了。

注册全局/局部 Vue 组件

在 Vue 中有两种注册组件的方式:

  • 全局注册, Vue.component(componentName, opts)
  • 局部注册,使用components属性
<div id="app"></div>
<script src="https://unpkg.com/vue"></script>
<script>
  // 全局注册 GlobalCmp组件
  Vue.component('GlobalCmp', {
    template: '<div>This is a Global Component</div>'
  })

  var app = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue!'
    },
    template: `<div>
                {{ message }}
                  <global-cmp />
                <local-cmp />
              </div>`,
    components: {
      // 局部注册 LocalCmp 组件。这里要注意的是组件 LocalCmp 只在父组件模板中可用
      // 所以这里,在父组件中使用了 template 选项
      localCmp: {
        template: '<div>This is a Local Component</div>'
      }
    }
  })
</script>

扩展 Vue 组件

我们知道,组件是高内聚,低耦合单元。但一个组件又不可能满足所有的业务需求,这就需要我们能够对组件进行扩展。Vue 为我们提供了以下两种扩展组件的方法:

  • Vue.extend
  • mixins

使用 Vue.extend 扩展组件

使用 Vue.extend() 方法,可以为 Vue 组件包装一个新的构造器,这个构造器在创建实例时,可以传入 opts 达到扩展组件的目的。看下面的例子:

<div id="app"></div>
<div id="app2"></div>
<script src="https://unpkg.com/vue"></script>
<script>
  // 全局注册 GlobalCmp组件
  var GlobalCmp = Vue.component('GlobalCmp', {
    data: function () {
      return {
        msg: 'Global Component'
      }
    },
    template: '<div>{{msg}}</div>'
  })

  // 为 GlobalCmp 包裹一个构造方法,以便扩展
  var ExtendGlobalCmp = Vue.extend(GlobalCmp)

  // 基于 ExtendGlobalCmp 创建实例,并增加扩展
  var app = new ExtendGlobalCmp({
    el: '#app',
    // 扩展的方法
    methods: {
      reverseMsg: function () {
        this.msg = this.msg.split('').reverse().join('')
      }
    },
    // 扩展的watcher
    watch: {
      msg: function (nv, ov) {
        alert(`new value=${nv}, old value=${ov}`)
      }
    }
  })

  // app2 不具有 reverseMsg, msg-watcher
  var app2 = new GlobalCmp({
    el: '#app2'
  })
</script>

这样,app 实例就具有 reverMsg 方法,以及 msg watcher,而最初的全局组件 GlobalCmp 并没有这些能力。

使用 mixins 扩展组件

使用 mixins 也可以实现上面基于 Vue.extend() 的效果。

<div id="app"></div>
<div id="app2"></div>
<script src="https://unpkg.com/vue"></script>
<script>
  // 全局注册 GlobalCmp组件
  var GlobalCmp = Vue.component('GlobalCmp', {
    data: function () {
      return {
        msg: 'Global Component'
      }
    },
    template: '<div>{{msg}}</div>'
  })

  // 定义 GlobalCmp 的扩展 mixin
  var mixinGlobalCmp = {
    // 扩展的方法
    methods: {
      reverseMsg: function () {
        this.msg = this.msg.split('').reverse().join('')
      }
    },
    // 扩展的watcher
    watch: {
      msg: function (nv, ov) {
        alert(`new value=${nv}, old value=${ov}`)
      }
    }
  }

  // 基于 GlobalCmp 创建实例,并使用 mixin 增加扩展
  var app = new GlobalCmp({
    el: '#app',
    mixins: [mixinGlobalCmp]
  })

  // 基于 GlobalCmp 创建实例,没有进行扩展
  // 所以 app2 不具有 reverseMsg, msg-watcher
  var app2 = new GlobalCmp({
    el: '#app2'
  })
</script>

使用 render 方法定义组件

render()方法让组件具有更好的编程性,而不必使用固定的模板。然而使用 render 方法编写 dom 结构非常麻烦,确实想大规模用的话,可以使用 jsx 插件

<div id="app">
  <global-cmp type="h1"></global-cmp>
  <global-cmp type="h4"></global-cmp>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
  // 带 render 方法的组件
  Vue.component('GlobalCmp', {
    props: {
      type: String
    },
    render: function (createElement) {
      var that = this
      return createElement(that.type, {
        on: {
          click: function () {
            alert(`msg: ${that.type}`)
          }
        }
      }, `${that.type}元素`)
    }
  })
  new Vue().$mount('#app')
</script>

小结

本文主要讲了以下几个 Vue 组件知识点:

  • Vue 组件都是 Vue 实例
  • 可以通过 Vue.extend(Component) 为组件包裹一个类,然后在 new 的时候传入 opts 达到扩展组件的目的
  • 可以通过 mixins 选项,方便地扩展组件
留言列表

    发表评论: