一开始,Vue 在其官方文档就说明了,Vue 组件都是 Vue 的实例。但由于我们使用 Vue 做项目时基本都是基于 *.vue 文件,全程也没有使用 new 去创建过实例,对Vue 组件都是 Vue 实例这句话并没有很直观的理解,也就谈不上什么深刻理解了。最近因项目原因复习了一遍 Vue 知识。本文记录个人觉得必须要牢记的 Vue 组件知识点。
<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 中有两种注册组件的方式:
<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.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 也可以实现上面基于 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 方法编写 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 组件知识点:
发表评论: