前面的话

  组件接受的选项大部分与Vue实例一样,而选项props是组件中非常重要的一个选项。在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。本文将详细介绍Vue组件选项props

父子级组件

  在介绍props之前,先介绍父子级组件的写法

  在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性

【错误写法】

  现在来介绍两种父子级组件的错误写法

  下面这种形式的写法是错误的,因为当子组件注册到父组件时,Vue.js会编译好父组件的模板,模板的内容已经决定了父组件将要渲染的HTML
  <parent>...</parent>运行时,它的一些子标签只会被当作普通的HTML来执行,<child></child>不是标准的HTML标签,会被浏览器直接忽视掉

<div id="example">
<parent>
<child></child>
<child></child>
</parent>
</div>

  在父组件标签之外使用子组件也是错误的

<div id="example">
<parent></parent>
<child></child>
</div>

【正确写法】

<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template: '<div>childNode</div>',
}
var parentNode = {
template: `
<div class="parent">
<child></child>
<child></child>
</div>
`,
components: {
'child': childNode
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

静态props

  组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,需要通过子组件的 props 选项

  使用Prop传递数据包括静态和动态两种形式,下面先介绍静态props

  子组件要显式地用 props 选项声明它期待获得的数据

var childNode = {
template: '<div>{{message}}</div>',
props:['message']
}

  静态Prop通过为子组件在父组件中的占位符添加特性的方式来达到传值的目的

<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template: '<div>{{message}}</div>',
props:['message']
}
var parentNode = {
template: `
<div class="parent">
<child message="aaa"></child>
<child message="bbb"></child>
</div>`,
components: {
'child': childNode
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

命名约定

  对于props声明的属性来说,在父级HTML模板中,属性名需要使用中划线写法

var parentNode = {
template: `
<div class="parent">
<child my-message="aaa"></child>
<child my-message="bbb"></child>
</div>`,
components: {
'child': childNode
}
};

  子级props属性声明时,使用小驼峰或者中划线写法都可以;而子级模板使用从父级传来的变量时,需要使用对应的小驼峰写法

var childNode = {
template: '<div>{{myMessage}}</div>',
props:['myMessage']
}
var childNode = {
template: '<div>{{myMessage}}</div>',
props:['my-message']
}

动态props

  在模板中,要动态地绑定父组件的数据到子模板的 props,与绑定到任何普通的HTML特性相类似,就是用 v-bind。每当父组件的数据变化时,该变化也会传导给子组件

var childNode = {
template: '<div>{{myMessage}}</div>',
props:['myMessage']
}
var parentNode = {
template: `
<div class="parent">
<child :my-message="data1"></child>
<child :my-message="data2"></child>
</div>`,
components: {
'child': childNode
},
data(){
return {
'data1':'aaa',
'data2':'bbb'
}
}
};

  

传递数字

  初学者常犯的一个错误是使用字面量语法传递数值

<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp>
<div id="example">
<my-parent></my-parent>
</div>
<script>
var childNode = {
template: '<div>{{myMessage}}的类型是{{type}}</div>',
props:['myMessage'],
computed:{
type(){
return typeof this.myMessage
}
}
}
var parentNode = {
template: `
<div class="parent">
<my-child my-message="1"></my-child>
</div>`,
components: {
'myChild': childNode
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'MyParent': parentNode
}
})
</script>

  因为它是一个字面 prop,它的值是字符串 "1" 而不是 number。如果想传递一个实际的 number,需要使用 v-bind,从而让它的值被当作JS表达式计算

<!-- 传递实际的 number -->
<comp v-bind:some-prop="1"></comp>
var parentNode = {
template: `
<div class="parent">
<my-child :my-message="1"></my-child>
</div>`,
components: {
'myChild': childNode
}
};

  或者可以使用动态props,在data属性中设置对应的数字1

var parentNode = {
template: `
<div class="parent">
<my-child :my-message="data"></my-child>
</div>`,
components: {
'myChild': childNode
},
data(){
return {
'data': 1
}
}
};

props验证

  可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue会发出警告。当组件给其他人使用时,这很有用

  要指定验证规格,需要用对象的形式,而不能用字符串数组

Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
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 value > 10
}
}
}
})

  type 可以是下面原生构造器

String
Number
Boolean
Function
Object
Array
Symbol

  type 也可以是一个自定义构造器函数,使用 instanceof 检测。

  当 prop 验证失败,Vue 会在抛出警告 (如果使用的是开发版本)。props会在组件实例创建之前进行校验,所以在 defaultvalidator 函数里,诸如 datacomputedmethods 等实例属性还无法使用

  下面是一个简单例子,如果传入子组件的message不是数字,则抛出警告

<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template: '<div>{{message}}</div>',
props:{
'message':Number
}
}
var parentNode = {
template: `
<div class="parent">
<child :message="msg"></child>
</div>`,
components: {
'child': childNode
},
data(){
return{
msg: '123'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

  传入数字123时,则无警告提示。传入字符串'123'时,结果如下所示

  将上面代码中,子组件的内容修改如下,可自定义验证函数,当函数返回为false时,则输出警告提示

var childNode = {
template: '<div>{{message}}</div>',
props:{
'message':{
validator: function (value) {
return value > 10
}
}
}
}

  在父组件中传入msg值为1,由于小于10,则输出警告提示

var parentNode = {
template: `
<div class="parent">
<child :message="msg"></child>
</div>`,
components: {
'child': childNode
},
data(){
return{
msg:1
}
}
};

单向数据流

  prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解

  另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着不应该在子组件内部改变 prop。如果这么做了,Vue 会在控制台给出警告

  下面是一个典型例子

<div id="example">
<parent></parent>
</div>
<script>
var childNode = {
template: `
<div class="child">
<div>
<span>子组件数据</span>
<input v-model="childMsg">
</div>
<p>{{childMsg}}</p>
</div>
`,
props:['childMsg']
}
var parentNode = {
template: `
<div class="parent">
<div>
<span>父组件数据</span>
<input v-model="msg">
</div>
<p>{{msg}}</p>
<child :child-msg="msg"></child>
</div>
`,
components: {
'child': childNode
},
data(){
return {
'msg':'match'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

  父组件数据变化时,子组件数据会相应变化;而子组件数据变化时,父组件数据不变,并在控制台显示警告

  修改子组件数据时,打开浏览器控制台会出现下图所示警告提示

修改prop数据

  修改prop中的数据,通常有以下两种原因

  1、prop 作为初始值传入后,子组件想把它当作局部数据来用

  2、prop 作为初始值传入,由子组件处理成其它数据输出

  [注意]JS中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态

  对于这两种情况,正确的应对方式是

  1、定义一个局部变量,并用 prop 的值初始化它

props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}

  但是,定义的局部变量counter只能接受initialCounter的初始值,当父组件要传递的值发生变化时,counter无法接收到最新值

<div id="example">
<parent></parent>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
template: `
<div class="child">
<div>
<span>子组件数据</span>
<input v-model="temp">
</div>
<p>{{temp}}</p>
</div>
`,
props:['childMsg'],
data(){
return{
temp:this.childMsg
}
},
};
var parentNode = {
template: `
<div class="parent">
<div>
<span>父组件数据</span>
<input v-model="msg">
</div>
<p>{{msg}}</p>
<child :child-msg="msg"></child>
</div>
`,
components: {
'child': childNode
},
data(){
return {
'msg':'match'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

  下面示例中,除初始值外,父组件的值无法更新到子组件中

  2、定义一个计算属性,处理 prop 的值并返回

props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}

  但是,由于是计算属性,则只能显示值,而不能设置值

<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
template: `
<div class="child">
<div>
<span>子组件数据</span>
<input v-model="temp">
</div>
<p>{{temp}}</p>
</div>
`,
props:['childMsg'],
computed:{
temp(){
return this.childMsg
}
},
};
var parentNode = {
template: `
<div class="parent">
<div>
<span>父组件数据</span>
<input v-model="msg">
</div>
<p>{{msg}}</p>
<child :child-msg="msg"></child>
</div>
`,
components: {
'child': childNode
},
data(){
return {
'msg':'match'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

  下面示例中,由于子组件使用的是计算属性,所以,子组件的数据无法手动修改

  3、更加妥帖的方案是,使用变量储存prop的初始值,并使用watch来观察prop的值的变化。发生变化时,更新变量的值

<div id="example">
<parent></parent>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
template: `
<div class="child">
<div>
<span>子组件数据</span>
<input v-model="temp">
</div>
<p>{{temp}}</p>
</div>
`,
props:['childMsg'],
data(){
return{
temp:this.childMsg
}
},
watch:{
childMsg(){
this.temp = this.childMsg
}
}
};
var parentNode = {
template: `
<div class="parent">
<div>
<span>父组件数据</span>
<input v-model="msg">
</div>
<p>{{msg}}</p>
<child :child-msg="msg"></child>
</div>
`,
components: {
'child': childNode
},
data(){
return {
'msg':'match'
}
}
};
// 创建根实例
new Vue({
el: '#example',
components: {
'parent': parentNode
}
})
</script>

Vue组件选项props的更多相关文章

  1. 【转存】Vue组件选项props

    原帖地址 前面的话 组件接受的选项大部分与Vue实例一样,而选项props是组件中非常重要的一个选项.在 Vue 中,父子组件的关系可以总结为 props down, events up.父组件通过  ...

  2. 第七十二篇:Vue组件的props

    好家伙, 1.组件的props props是组件的自定义属性,在封装通用组件的时候,合理的使用props可以极大的提高组件的复用性 来假设一下,如果我们需要两个组件分别显示不同的值 目录结构如下: H ...

  3. Vue组件之props,$emit与$on以及slot分发

    组件实例之间的作用域是孤立存在,要让它们之间的信息互通,就必须采用组件的通信方式  props用于父组件向子组件传达信息 1.静态方式 eg: <body> <div id=&quo ...

  4. vue 组件属性props,特性驼峰命名,连接线使用

    网址:https://www.cnblogs.com/alasq/p/6363160.html 总结如下:vue的组件的props属性支持驼峰命名,不支持连接线命名,使用是用连接线进行赋值或者数据绑定 ...

  5. vue组件的props

    刚开始学习vue组件的时候经常被 props这个传值搞晕,做个笔记 Vue.component('item', { template: '#item-template', props: { model ...

  6. vue 组件开发 props 验证

    使用props 在Vue中父组件向子组件中传送数据是通过props实现的,一个简单的使用props的例子: <!DOCTYPE html> <html> <head> ...

  7. vue组件之属性Props

    组件的属性和事件 父子组件之间的通信 父子组件之间的通信就是 props down,events up,父组件通过 属性props向下传递数据给子组件,子组件通过 事件events 给父组件发送消息. ...

  8. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  9. Vue组件-组件的属性

    在html中使用元素,会有一些属性,如class,id,还可以绑定事件,自定义组件也是可以的.当在一个组件中,使用了其他自定义组件时,就会利用子组件的属性和事件来和父组件进行数据交流. 比如,子组件需 ...

随机推荐

  1. tokuDB 安装与备份小记

    线上的数据增长越来越快,数据量的增长也愈来愈大,尤其是日志类数据,这对于数据迁移.数据备份恢复而言,都是一个非常大的挑战. 于是想到了 13 年开源 tokuDB 存储引擎,来解决我们迫在眉睫的容量问 ...

  2. 从浅入深剖析angular表单验证

    最近手上维护的组件剩下的BUG都是表单验证,而且公司的表单验证那块代码经历的几代人,里面的逻辑开始变得不清晰,而且代码结构不是很angular. 是很有必要深入了解表单验证. 入门之前,我觉得应该先了 ...

  3. usaco training 4.1.1 麦香牛块 题解

    Beef McNuggets题解 Hubert Chen Farmer Brown's cows are up in arms, having heard that McDonalds is cons ...

  4. JAVA - 深入JAVA 虚拟机 1

    Java虚拟机与程序的生命周期 Java虚拟机将结束生命周期 1.call System.exit(n) Terminates the currently running JVM. 2.程序正常执行结 ...

  5. 进击的AssetBundles和它的工具们

    0x00 前言 周末的时候在家看了下去年的Unite16 LA的视频.其中一个session很有趣,是AssetBundles开发团队Reichert的一个"总结过往,畅想未来"的 ...

  6. Bootstrap按钮插件

    前面的话 按钮插件提供了一组可以控制按钮多种状态的功能,比如按钮的禁用状态.正在加载状态.正常状态等.本文将详细介绍Bootstrap按钮插件 加载状态 通过按钮可以设计状态提示,当单击按钮时,会显示 ...

  7. 元组-tuple功能介绍

    #元组 不可变类型 相当于只读的列表,不可被修改,不可被修改哦 ##创建元组最后加,最后加, 形成良好的习惯 """ tuple() -> empty tuple ...

  8. Java条形码/二维码生成和解析

    注意-本类依赖jar包文件:core.jar和zxing-javase.jar 下载jar文件,到本博客文件栏目下载. import com.google.zxing.BarcodeFormat; i ...

  9. STL系列

    STL—对象的构造与析构 STL—内存的配置与释放 STL—vector STL—vector空间的动态增长

  10. linux中grep命令的用法

    作为linux中最为常用的三大文本(awk,sed,grep)处理工具之一,掌握好其用法是很有必要的. 首先谈一下grep命令的常用格式为:[grep  [选项]  "模式"  [ ...