props 类型
为何须要 props 类型呢?就好比咱们子组件须要用到父组件的数据,咱们到底该使用何种方式传递进去呢?咱们都知道在原生 DOM 中有一种 data- 属性,能够将数据绑定,因此相似这种方式,props 就应运而生了。vue
咱们仍是接着上节课的例子,在 src/views/TestCom.vue
,接收父组件传递进来的属性 title
:web
<template>
<div class="test-com-wrap">{{title}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
},
};
</script>
而后咱们在 src/views/TemplateM.vue
来使用 TestCom
组件,向 TestCom
组件传递 title
属性:数组
<template>t
<div class="template-m-wrap">
<test-com title="这个是组件"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
咱们访问 http://localhost:8080/template_m
浏览实际效果以下:浏览器
传递静态或动态 Prop
从上面咱们知道咱们直接像下面这段代码,就是咱们所说的静态属性:微信
<test-com title="这是组件"></test-com>
若是咱们把这个 title
属性绑定一个变量,那就是动态绑定属性:app
<template>t
<div class="template-m-wrap">
<test-com :title="searchText"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "这个是组件",
};
},
};
</script>
效果仍是跟上面同样:编辑器
传入一个数字
假如子组件须要接收父组件的一个数值,那么咱们能够给 props
传递一个数字类型,接下来咱们在 src/views/TestCom.vue
来添加一个数字类型的 props
:函数
<template>
<div class="test-com-wrap">{{title}}-{{num}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0
}
},
};
</script>
在 src/views/TemplateM.vue
来传递一个数字:post
<template>
<div class="template-m-wrap">
<test-com title="这个是组件" :num="42"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
咱们来看看效果如何:flex
传入一个布尔值
咱们一样在 src/views/TestCom.vue
设置一个布尔类型的 props:
<template>
<div class="test-com-wrap">{{title}}-{{num}}-{{bool}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0
},
bool: {
type: Boolean,
default: false
}
},
};
</script>
在 src/views/TemplateM.vue
来使用:
<template>
<div class="template-m-wrap">
<test-com title="这个是组件" :num="42" :bool="true"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
最后咱们来查看下效果:
传入一个数组
咱们一样在 src/views/TestCom.vue
接收一个数组类型的 props:
<template>
<div class="test-com-wrap">
{{ title }}-{{ num }}-{{ bool }}
<ul v-if="arr.length">
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0,
},
bool: {
type: Boolean,
default: false,
},
arr: {
type: Array,
default: () => ([]),
},
},
};
</script>
在 src/views/TemplateM.vue
来使用:
<template>
<div class="template-m-wrap">
<test-com title="这个是组件" :num="42" :bool="true" :arr="arr"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
arr: ['code', 'Ken', '理财投资']
};
},
};
</script>
来看看效果以下:
传入一个对象
咱们一样在 src/views/TestCom.vue
接收一个 Object 类型的 props:
<template>
<div class="test-com-wrap">
{{ title }}-{{ num }}-{{ bool }}
<ul v-if="arr.length">
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
{{obj.name}}
</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0,
},
bool: {
type: Boolean,
default: false,
},
arr: {
type: Array,
default: () => ([]),
},
obj: {
type: Object,
default: () => ({})
}
},
};
</script>
在 src/views/TemplateM.vue
使用:
<template>
<div class="template-m-wrap">
<test-com title="这个是组件" :num="42" :bool="true" :arr="arr" :obj="obj"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
arr: ['code', 'Ken', '理财投资'],
obj: {
name: "Ken"
}
};
},
};
</script>
来看看效果以下:
传入一个对象的全部 property
若是你想要将一个对象的全部 property 都做为 prop 传入,你可使用不带参数的 v-bind
(取代 v-bind
:prop-name
)。例如,对于一个给定的对象 post
:
post: {
id: 1,
title: 'My Journey with Vue'
}
下面的模板:
<test-com v-bind="post"></test-com>
等价于:
<test-com v-bind:id="post.id" v-bind:title="post.title"></test-com>
单向数据流
全部的 prop 都使得其父子 prop 之间造成了一个「单向下行绑定」:父级 prop 的更新会向下流动到子组件中,可是反过来则不行。这样会防止从子组件意外变动父级组件的状态,从而致使你的应用的数据流向难以理解。
另外,每次父级组件发生变动时,子组件中全部的 prop 都将会刷新为最新的值。这意味着你「不」应该在一个子组件内部改变 prop。若是你这样作了,Vue 会在浏览器的控制台中发出警告。
这里有两种常见的试图变动一个 prop 的情形:
-
这个 「prop 用来传递一个初始值;这个子组件接下来但愿将其做为一个本地的 prop 数据来使用」。在这种状况下,最好定义一个本地的 data property 并将这个 prop 用做其初始值
props: ['initialCounter'],
data() {
return {
counter: this.initialCounter
}
}
-
这个 prop 以一种原始的值传入且须要进行转换**。在这种状况下,最好使用这个 prop 的值来定义一个计算属性
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
Prop 验证
咱们能够为组件的 prop 指定验证要求,例如你知道的这些类型。若是有一个需求没有被知足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤为有帮助。
为了定制 prop 的验证方式,你能够为 props
中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
app.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
}
},
// 具备默认值的函数
propG: {
type: Function,
// 与对象或数组默认值不一样,这不是一个工厂函数 —— 这是一个用做默认值的函数
default: function() {
return 'Default function'
}
}
}
})
类型检查
type
能够是下列原生构造函数中的一个:
-
String -
Number -
Boolean -
Array -
Object -
Date -
Function -
Symbol
Prop 的大小写 (camelCase vs kebab-case)
HTML 中的 attribute 名是大小写不敏感的,因此浏览器会把全部大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名须要使用其等价的 kebab-case (短横线分隔命名) 命名:
const app = Vue.createApp({})
app.component('blog-post', {
// camelCase in JavaScript
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
使用以下:
<blog-post post-title="hello!"></blog-post>
重申一次,若是你使用字符串模板,那么这个限制就不存在了。
本文分享自微信公众号 - 人生代码(lijinwen1996329ken)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。