组件的分类
- 全局组件 : 可以声明一次在任何地方使用(一般写插件的时候全局使用的多一点)
- 局部组件: 必须告诉这个组件属于谁(一般用局部比较好)
props是只读的,vue底层会检测你对props的修改,如果进行了修改,控制台会报错,必须修改,就复制一份到data中,通过data去修改数据。
我们在data里面重新定义一个变量去接收props属性。这个变量最好不要重名,重名的话,优先获取props属性值,优先级props>data。
全局组件(component)
全局注册的组件可以在随后创建的 app 实例模板中使用,也包括根实例组件树中的所有子组件的模板中
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<runoob></runoob>
<!-- 组件间数据相互独立 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
// 创建一个Vue 应用
const app = Vue.createApp({})
// 定义一个名为 runoob的新全局组件
app.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
// 定义一个名为 button-counter的新全局组件
app.component('button-counter', {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">
点了 {{ count }} 次!
</button>`
})
app.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
app.mount('#app')
</script>
浏览器渲染
局部组件(components)
//对象
const ComponentA = {
/* ... */
}
const ComponentB = {
/* ... */
}
//使用
const app = Vue.createApp({
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字(component-a、component-b),其属性值就是这个组件的选项对象(ComponentA、ComponentB)。
我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
定义两个局部组件
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<runoob-a></runoob-a>
<runoob-b></runoob-b>
</div>
<script>
var runoobA = {
template: '<h1>自定义组件A!</h1>'
}
var runoobB = {
template: '<h1>自定义组件B!</h1>'
}
const app = Vue.createApp({
components: {
'runoob-a': runoobA,
'runoob-b': runoobB,
}
})
app.mount('#app')
</script>
浏览器渲染结果:
Prop
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<site-name name="Muze" mail="1@1.com"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', {
props: ['name', 'mail'],
template: `<h2>昵称:{{ name }}<br />邮箱:{{ mail }}</h2>`
})
app.mount('#app')
</script>
浏览器渲染结果
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
<div id="app">
<site-info v-for="site in sites" :id="site.id" :title="site.title"></site-info>
</div>
<script>
const Site = {
data() {
return {
sites: [
{ id: 1, title: 'Google' },
{ id: 2, title: 'Runoob' },
{ id: 3, title: 'Taobao' }
]
}
}
}
const app = Vue.createApp(Site)
app.component('site-info', {
props: ['id', 'title'],
template: `<h4>{{ id }} - {{ title }}</h4>`
})
app.mount('#app')
</script>
浏览器演示效果
限制
- 类型属性:type:xx
- 必传属性:required:true
- 默认属性:default:xx
Prop 验证
组件可以为 props 指定验证要求。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
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 ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
type 可以是下面原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
type 也可以是一个自定义构造器,使用 instanceof 检测。
例子
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<site-name name="Muze" mail="1@1.com" age="18"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', {
props: {
//昵称
"name": {
type: String, //类型属性
required: true, //必传属性
default: "外星人", //默认值
},
//邮箱
"mail": {
type: String,
required: false,
default: "myemail@email.com",
},
//年龄
"age": {
type: Number,
required: true,
default: "未知",
}
},
template: `<h2>
昵称:{{ name }}<br />
邮箱:{{ mail }}<br />
年龄:{{ age }}</h2>`
})
app.mount('#app')
</script>
浏览器渲染
组件接收外部传来数据的三种方式:
(1)只接收:props: ['name','age','sex']
(2)接收并限制类型:props: { "name":Number }
(3)限制类型、限制必要性指定默认值:
props:{
"name":{
type:String,
required:true
},
"age":{
type:Number,
default:18
},
"sex":{
type:String,
default:'男'
},
},
年龄+1岁
<site-name name="Muze" mail="1@1.com" :age="18"></site-name>
年龄:{{ age+1 }}</h2>
做个按钮,年龄点击变99岁
待完善
实战代码
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<h1>{{ msg }}</h1>
<button @click="add">计数器:{{counte}}</button>
<site-name></site-name>
</div>
<script>
//父组件
const appRoot = {
data() {
return {
msg: "个人基本信息",
counte: 1,
}
},
methods: {
add() {
this.counte += 1;
}
},
}
app = Vue.createApp(appRoot);
//子组件
app.component('site-name', {
props: {
//年龄
"age": {
type: Number,
required: true,
default: "18",
}
},
template: `<h2>年龄:{{ age }}</h2>`,
})
app.mount('#app');
</script>
浏览器渲染