컴포넌트에서 허용하는 대부분의 옵션은 Vue 인스턴스와 동일하며 옵션 props는 컴포넌트에서 매우 중요한 옵션입니다. Vue에서 상위 컴포넌트와 하위 컴포넌트 간의 관계는 props down, events up으로 요약될 수 있습니다. 상위 컴포넌트는 props를 통해 하위 컴포넌트에 데이터를 전달하고, 하위 컴포넌트는 이벤트를 통해 상위 컴포넌트에 메시지를 보냅니다. 이번 글에서는 Vue 컴포넌트 옵션 props를 자세히 소개하겠습니다
컴포넌트 인스턴스의 범위는 격리되어 있습니다. 즉, 하위 구성 요소의 템플릿 내에서 상위 구성 요소의 데이터를 직접 참조할 수 없으며 참조해서는 안 됩니다. 하위 구성 요소가 상위 구성 요소의 데이터를 사용하도록 허용하려면 하위 구성 요소의 props 옵션을 전달해야 합니다
. Prop을 사용하여 데이터를 전달하려면 정적 및 동적 양식을 먼저 도입해야 합니다
. 명시적으로 props 옵션을 사용하여 획득할 것으로 예상되는 데이터를 선언합니다<code>props
选项声明它期待获得的数据
var childNode = { template: '<p>{{message}}</p>', props:['message'] }
静态Prop通过为子组件在父组件中的占位符添加特性的方式来达到传值的目的
<p id="example"> <parent></parent></p>
<script>var childNode = { template: '<p>{{message}}</p>', props:['message'] }var parentNode = { template: ` <p class="parent"> <child message="aaa"></child> <child message="bbb"></child> </p>`, components: { 'child': childNode } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
对于props声明的属性来说,在父级HTML模板中,属性名需要使用中划线写法
var parentNode = { template: ` <p class="parent"> <child my-message="aaa"></child> <child my-message="bbb"></child> </p>`, components: { 'child': childNode } };
子级props属性声明时,使用小驼峰或者中划线写法都可以;而子级模板使用从父级传来的变量时,需要使用对应的小驼峰写法
var childNode = { template: '<p>{{myMessage}}</p>', props:['myMessage'] }
var childNode = { template: '<p>{{myMessage}}</p>', props:['my-message'] }
在模板中,要动态地绑定父组件的数据到子模板的 props,与绑定到任何普通的HTML特性相类似,就是用 v-bind
。每当父组件的数据变化时,该变化也会传导给子组件
var childNode = { template: '<p>{{myMessage}}</p>', props:['myMessage'] }
var parentNode = { template: ` <p class="parent"> <child :my-message="data1"></child> <child :my-message="data2"></child> </p>`, components: { 'child': childNode }, data(){ return { 'data1':'aaa', 'data2':'bbb' } } };
初学者常犯的一个错误是使用字面量语法传递数值
<!-- 传递了一个字符串 "1" --><comp some-prop="1"></comp>
<p id="example"> <my-parent></my-parent></p>
<script>var childNode = { template: '<p>{{myMessage}}的类型是{{type}}</p>', props:['myMessage'], computed:{ type(){ return typeof this.myMessage } } }var parentNode = { template: ` <p class="parent"> <my-child my-message="1"></my-child> </p>`, 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: ` <p class="parent"> <my-child :my-message="1"></my-child> </p>`, components: { 'myChild': childNode } };
或者可以使用动态props,在data属性中设置对应的数字1
var parentNode = { template: ` <p class="parent"> <my-child :my-message="data"></my-child> </p>`, components: { 'myChild': childNode }, data(){ return { 'data': 1 } } };
可以为组件的 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会在组件实例创建之前进行校验,所以在 default
或 validator
函数里,诸如 data
、computed
或 methods
<p id="example"> <parent></parent> </p>
<script> var childNode = { template: '<p>{{message}}</p>', props:{ 'message':Number } } var parentNode = { template: ` <p class="parent"> <child :message="msg"></child> </p>`, components: { 'child': childNode }, data(){ return{ msg: '123' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>
var childNode = { template: '<p>{{message}}</p>', props:{ 'message':{ validator: function (value) { return value > 10 } } } }
명명 규칙
props의 경우 선언된 속성의 경우 상위 HTML 템플릿에서 속성 이름을 밑줄로 작성해야 합니다.
var parentNode = { template: ` <p class="parent"> <child :message="msg"></child> </p>`, components: { 'child': childNode }, data(){ return{ msg:1 } } };
하위 props 속성을 선언할 때 낙타 대문자 또는 밑줄로 작성할 수 있습니다. 하위 템플릿에서 상위 템플릿에서 전달된 변수를 사용할 경우 해당 카멜 표기법을 사용해야 합니다
<p id="example"> <parent></parent> </p>
<script> var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="childMsg"> </p> <p>{{childMsg}}</p> </p> `, props:['childMsg'] } var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>
v-bind
를 사용하여 일반 HTML 기능에 바인딩됩니다. 상위 구성 요소의 데이터가 변경될 때마다 해당 변경 사항은 하위 구성 요소에도 전송됩니다🎜🎜🎜props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
<p id="example"> <parent></parent></p><script>var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], data(){ return{ temp:this.childMsg } }, };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
<script src="https://unpkg.com/vue"></script><script>var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], computed:{ temp(){ return this.childMsg } }, };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
<p id="example"> <parent></parent></p><script>var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], data(){ return{ temp:this.childMsg } }, watch:{ childMsg(){ this.temp = this.childMsg } } };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
"1"
문자열입니다. 실제 숫자를 전달하려면 해당 값이 JS 표현식 🎜🎜🎜rrreee🎜🎜🎜🎜rrreee🎜🎜🎜🎜🎜 또는 동적 props를 사용하여 데이터에 해당 숫자 1🎜을 설정할 수도 있습니다. attribute 🎜🎜rrreee🎜🎜🎜🎜🎜props verify🎜🎜 컴포넌트의 props에 대한 검증 사양을 지정할 수 있습니다. Vue는 들어오는 데이터가 사양을 충족하지 않으면 경고를 발행합니다. 다른 사람이 컴포넌트를 사용할 때 유용합니다🎜🎜 검증 사양을 지정하려면 문자열 배열이 아닌 객체의 형태를 사용해야 합니다🎜🎜🎜rrreee🎜🎜🎜 type
은 다음과 같을 수 있습니다 기본 구성 생성자 🎜🎜🎜rrreee🎜🎜🎜 type
은 instanceof
를 사용하여 감지하는 사용자 정의 생성자 함수일 수도 있습니다. 🎜🎜 prop 검증이 실패하면 Vue는 경고를 표시합니다(개발 버전을 사용하는 경우). Props는 구성 요소 인스턴스가 생성되기 전에 확인되므로 data
와 같은 default
또는 validator
함수에서 확인됩니다. , computed
또는 methods
와 같은 인스턴스 속성은 아직 사용할 수 없습니다🎜🎜 다음은 하위 구성 요소에 전달된 메시지가 숫자가 아닌 경우 경고가 표시됩니다. be 던져🎜🎜🎜rrreee🎜 🎜🎜🎜rrreee🎜🎜🎜 숫자 123이 전달되면 경고가 발생하지 않습니다. 문자열 '123'이 전달되면 결과는 다음과 같습니다. 🎜🎜🎜🎜🎜 위 코드에서 하위 구성 요소의 내용을 다음과 같이 수정합니다. 함수가 false를 반환하면 경고 메시지가 표시됩니다. 출력 🎜🎜🎜 rrreee🎜🎜🎜 상위 컴포넌트에 들어오는 msg 값은 1입니다. 10 미만이므로 경고 프롬프트가 출력됩니다🎜🎜🎜rrreee🎜🎜🎜🎜🎜🎜🎜🎜단방향 데이터 흐름🎜🎜 prop은 단방향 바인딩입니다. 부모 구성 요소의 속성이 변경되면 해당 속성이 자식 구성 요소로 전파되지만 그 반대 방향으로는 전파되지 않습니다. 이는 하위 구성 요소가 실수로 상위 구성 요소의 상태를 수정하여 애플리케이션의 데이터 흐름을 이해하기 어렵게 만드는 것을 방지하기 위한 것입니다🎜另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着不应该在子组件内部改变 prop。如果这么做了,Vue 会在控制台给出警告
下面是一个典型例子
<p id="example"> <parent></parent> </p>
<script> var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="childMsg"> </p> <p>{{childMsg}}</p> </p> `, props:['childMsg'] } var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } }; // 创建根实例 new Vue({ el: '#example', components: { 'parent': parentNode } }) </script>
父组件数据变化时,子组件数据会相应变化;而子组件数据变化时,父组件数据不变,并在控制台显示警告
修改子组件数据时,打开浏览器控制台会出现下图所示警告提示
修改prop中的数据,通常有以下两种原因
1、prop 作为初始值传入后,子组件想把它当作局部数据来用
2、prop 作为初始值传入,由子组件处理成其它数据输出
[注意]JS中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态
对于这两种情况,正确的应对方式是
1、定义一个局部变量,并用 prop 的值初始化它
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
但是,定义的局部变量counter只能接受initialCounter的初始值,当父组件要传递的值发生变化时,counter无法接收到最新值
<p id="example"> <parent></parent></p><script>var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], data(){ return{ temp:this.childMsg } }, };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, 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: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], computed:{ temp(){ return this.childMsg } }, };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
下面示例中,由于子组件使用的是计算属性,所以,子组件的数据无法手动修改
3、更加妥帖的方案是,使用变量储存prop的初始值,并使用watch来观察prop的值的变化。发生变化时,更新变量的值
<p id="example"> <parent></parent></p><script>var childNode = { template: ` <p class="child"> <p> <span>子组件数据</span> <input v-model="temp"> </p> <p>{{temp}}</p> </p> `, props:['childMsg'], data(){ return{ temp:this.childMsg } }, watch:{ childMsg(){ this.temp = this.childMsg } } };var parentNode = { template: ` <p class="parent"> <p> <span>父组件数据</span> <input v-model="msg"> </p> <p>{{msg}}</p> <child :child-msg="msg"></child> </p> `, components: { 'child': childNode }, data(){ return { 'msg':'match' } } };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
위 내용은 Vue 구성요소 옵션 소품의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!