首先,本篇文章是由一串错误的代码引出的…
//需求:实现父组件向子组件传递数据
<body>
<div id="app">
<child :message="parentMsg"></child>
</div>
<template id="child">
<div>
{{message}}
</div>
</template>
<script>
// 最初写法================================报错
// Vue.component('child', {
// template: '#child',
// data() {
// return {}
// },
// props: {
// message: {
// type: String,
// default: 'aaaaaa'
// }
// }
// })
// ================================报错
// 正确写法================================
const child = Vue.extend({
template: '#child',
data() {
return {}
},
props: {
message: {
type: String,
default: 'aaaaaa'
}
}
})
// 正确写法================================
const app = new Vue({
el: "#app",
data: {
parentMsg: '我是父组件parentMsg'
},
methods: {
},
components: { child },
})
</script>
</body>
毫不意外,按照最初写法将出现的结果是一串爆红——vue.js:634 [Vue warn]: Failed to mount component: template or render function not defined.
,意思是mount组件失败:模板或渲染函数没有定义。不要慌,有错误就会有解决办法,我们来研究一番!
先来解释一下我最初为什么会这么写,有两点原因:
Vue.component
是创建组件的方式之一,但是我误以为它是简写方式(我写的时候还在寻思着,这也不简写吧,还是那么复杂,甚至有一瞬间我分不清这是组件还是组件构造器)——涉及知识范围:组件和组件构造器的区分。Vue.component
来创建全局组件,而且全局组件不是所有组件都能使用的嘛?那么我就在根组件中components它为什么不可以嘞(我甚至还超级“理直气壮”!)——涉及知识范围:全局组件和局部组件的使用。OK,分析完错误原因之后,我们就来理一理它们之间的关系!
我们先来写一个组件的案例:
<body>
<div id="app">
<!-- 3、使用组件 -->
<my-cpn></my-cpn>
</div>
<script>
// 1、创建组件构造器对象
const cpnC = Vue.extend({
template: `
早上好!
中午好!
晚上好!
`
})
// 2、注册组件
Vue.component('my-cpn', cpnC)
//根组件
const app = new Vue({
el: "#app",
data: {
},
methods: {
},
})
</script>
</body>
vue.js中创建组件有三大步骤:
定义组件 ——
Vue.extend()
创建的是一个组件构造器, 通常在创建组件构造器时,传入template
代表我们自定义组件的模板,即const cpnC = Vue.extend({ template:' ' })
;Vue.component('组件名称',{ 组件构造器 })
直接创建组件(全局组件)。注册组件 ——
Vue.component('标签名', 组件名)
注册组件时,组件的注册是全局的; const app = new Vue({
el: "#app",
// 注册局部组件
components: {
// cpn使用组件时的标签名,cpnC组件名
cpn: cpnC
}
})
extend创建的是一个组件构造器,而不是一个具体的组件实例,所以直接使用无法生效。
组件构造器相当于Vue.component()方法的第二个参数部分
组件构造器的正确打开方式(有效使用):
//正常写法:
const child = Vue.extend({
template: '#child',
data() {
return {}
},
props: {
message: {
type: String,
default: 'aaaaaa'
}
}
})
//简写形式:
const child = {
template: '#child',
data() {
return {}
},
props: {
message: {
type: String,
default: 'aaaaaa'
}
}
}
方式一:通过构造器创建组件,通过Vue.component('标签名', 组件名)
注册组件
<body>
<div id="app">
<!-- 3、使用组件 -->
<my-cpn></my-cpn>
</div>
<script>
// 1、创建组件构造器对象
const cpnC = Vue.extend({
template: `
早上好!
中午好!
晚上好!
`
})
// 2、注册全局组件
Vue.component('my-cpn', cpnC)
//根组件
const app = new Vue({
el: "#app",
data: {
},
methods: {
},
})
</script>
</body>
方式二:使用Vue.component('组件名称',{ 组件构造器 })
直接创建组件(全局组件)
<body>
<div id="app">
<cpn1></cpn1>
</div>
<script>
// 1.创建组件构造器对象
// const cpnC1 = Vue.extend()
// 2.注册组件
Vue.component('cpn1', {
template: `
你好吗
你好嘛
你好么
`
})
// 根组件
const app = new Vue({
el: "#app",
data: {
},
methods: {
},
})
</script>
</body>
注意:
<body>
<div id="app">
<!-- 3、使用组件 -->
<cpn></cpn>
</div>
<script>
// 1、创建组件构造器对象
const cpnC = Vue.extend({
template: `
早上好!
中午好!
晚上好!
`
})
//根组件
const app = new Vue({
el: "#app",
data: {
},
methods: {
},
// 2、注册全局组件
components: {
// cpn使用组件时的标签名
cpn: cpnC
}
})
</script>
</body>
注意: 使用局部组件时,需要在components属性中注册才能使用!!!