关于Vue中props的详解

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。

  • 也就是props是子组件访问父组件数据的唯一接口。

  • 一个组件可以直接在模板里面渲染data里面的数据(双大括号)。

  • 子组件不能直接在模板里面渲染父元素的数据。

  • 如果子组件想要引用父元素的数据,那么就在prop里面声明一个变量(比如a),这个变量就可以引用父元素的数据。然后在模板里渲染这个变量(前面的a),这时候渲染出来的就是父元素里面的数据。

  • 属性是驼峰式命名,在html中替换成短横线分割式命名

  • prop类型可以是字符串,数字、boolear、数组、对象
    传递静态或动态 Prop

<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child> 
<script>
    Vue.component('child', {
        // 在 JavaScript 中使用 camelCase
        props: ['myMessage'],
        template: '<span>{{ myMessage }}</span>'
    })
</script>
单向数据流:props是单向绑定
  • 当父组件的属性变化时,将传导给子组件,但是反过来不会。

  • 每次父组件更新时,子组件的所有 prop 都会更新为最新值。

  • 不要在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。

在两种情况下,我们很容易忍不住想去修改 prop 中数据:

Prop 作为初始值传入后,子组件想把它当作局部数据来用;
Prop 作为原始数据传入,由子组件处理成其它数据输出。对这两种情况,正确的应对方式是:
定义一个局部变量,并用 prop 的值初始化它:

props: ['initialCounter'],

data: function () {

  return { counter: this.initialCounter }

}
  • 定义一个计算属性,处理 prop 的值并返回:

    props: ['size'],

    computed: {

      normalizedSize: function () {

        return this.size.trim().toLowerCase()

      }

    }

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


    <div id="app3">

        <my-component :object='object'></my-component>

    </div>

    <script src="http://vuejs.org/js/vue.min.js"></script>

    <script>

        //

        var mycom = Vue.component('my-component', {

            //添加一个input改变子组件的childOject,那么父元素的object也会被改变,但是Vue没有报错!

            template: '<p>{{ object.name }} is {{ object.age }} years old.<br><input v-model="childObject.name" type="text"></p>',

            props: ['object','school'],

            data: function () {

                // 子组件的childObject 和 父组件的object 指向同一个对象

                return {

                    childObject: this.object

                }

            }

        });

        var app3 = new Vue({

            el: '#app3',

            data: {

                object:{

                    name: 'Xueying',

                    age: '21',

                },

                school:'SCUT',

            },

        })

    </script>

prop验证
  • 为了定制 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 } } } })

eg:

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>Vue Study</title>

</head>

<body>

 

    <div id="app">

        <foo-component :foo-message="fooMessage"></foo-component>  

    </div>

 

<script type="text/javascript" src="lib/vue.js"></script>

<script type="text/javascript">

 

    var fooComponent = {

        props: {

            fooMessage: Number

        },

        template: '<div> {{ fooMessage }} </div>'

    };

 

    var vm = new Vue({

        components: {

            'foo-component': fooComponent

        },

        el: '#app',

        data: {

            fooMessage: 123

        }

    });

 

</script>

</body>

</html>

type接受多个类型:当参数是多种类型的其中一个的时候,使用数组来表示

 var fooComponent = {
       props: {
             fooMessage: [Number, String]
        },
        template: '<div> {{ fooMessage }} </div>'
     };
  • type能够指定的类型
  • 当type的类型为Array或者Object的时候default必须是一个函数:
  • required可以使用required选项来声明这个参数是否必须传入
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue Study</title>
</head>
<body>
 
    <div id="app">
        <foo-component :foo-message="fooMessage"></foo-component>  
    </div>
 
<script type="text/javascript" src="lib/vue.js"></script>
<script type="text/javascript">
 
    var fooComponent = {
        props: {
            fooMessage: {
                type: Number,
                required: true
            }
        },
        template: '<div> {{ fooMessage }} </div>'
    };
 
    var vm = new Vue({
        components: {
            'foo-component': fooComponent
        },
        el: '#app',
        data: {
            fooMessage: 256
        }
    });
 
</script>
</body>
</html>

String

Number

Boolean

Function

Object

Array

Symbol

非Prop的特性
  • 什么是prop的特性?

—指传向一个组件,但是该组件没有添加到props中如何在子组件访问


Vue.component('test-prop', {
  // 在组件props中只定义了param1
  props: ['param1'],
  inheritAttrs: false,  // 详情见 ↓ 附录1
  template: '<div></div>',
  mounted() {
    console.log(this.param1);  // 值1
    console.log(this.param2);  // undefined

    console.log(this.$attrs); // 返回父作用域中非 prop 的特性 (class 和 style 除外)的对象集合
    console.log(this.$attrs.param1);  // undefined
    console.log(this.$attrs.param2);  // 值2

    console.log(this.$listeners);  // 返回父作用域中的 (不含 .native 修饰器的) v-on 事件集合
    console.log(this.$listeners.event1);  // fn1
    console.log(this.$listeners.event2);  // undefined
    this.$emit('event1');
  }
})
<test-prop 
  param1="值1" 
  param2="值2" 
  v-on:event1="fn1" 
  v-on:event2.native="fn2"></test-prop>
<!-- 此时 传入的param2 即为 非 prop 的特性 -->

通过 $attrs 及 $listeners 属性可以降低在不使用Vuex以及事件总线的情况下,组件跨级props以及事件传递的复杂度。

$parent

p a r e n t 也 可 以 用 来 访 问 父 组 件 的 数 据 。 而 且 子 组 件 可 以 通 过 parent 也可以用来访问父组件的数据。而且子组件可以通过 parent访parent 来直接修改父组件的数据,不会报错!


    <blog-post :object1="obj" :obj1="'hhhhh'"></blog-post>
</div>
<script>
    Vue.component('blog-post', {
        props: ['title','object1'],
        template: '<p>{{ object1.name }} is {{ object1.age }} years old.<br><input v-model="childObject.name" type="text">,</p>',
        data:function () {
            return {childObject:this.object1}
        },
        mounted(){
            console.log(this.object1);
            console.log(this.$attrs.obj1);
            console.log(this.$parent.text);
        }
    })
    new Vue({
        el:'.app',
        data:{
            text:'12345',
            obj:{
                name:'xiaomei',
                age:'21'
            }
        }
    })
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值