组件(2):使用Prop下发数据

数据下发

组件实例的做用域是相互独立的,父、子组件之间没法进行数据的共享。
若是想在子组件模板中使用父组件的数据,能够经过Prop将父组件的数据下发到子组件。子组件用props选项声明它预期的数据。javascript

为了传递数据,父组件必须先在子组件自定义标签的特性上绑定数据,绑定的值分两种状况解析:html

  • 字面量 prop="value"
  • 表达式(动态绑定) v-bind:prop="expression"
  • 表达式特例 v-bind="Object"
new Vue({
    el: '#app-1',
    data: {
        parentMsg: 'root\'s dynamic data',
        parentObj: {
            text:'hello vue!',
            isShow: true
        },
    },
    components: {
        'component-1': {
            props: ['expectMsg','expectDynamicMsg','expectObj','text','isShow'],
            template: '\
            <div>\
                <p>{{expectMsg}}</p>\
                <p>{{expectDynamicMsg}}</p>\
                <p v-show="expectObj.isShow">{{expectObj.text}}</p>\
                <p v-show="isShow">{{text}}</p>\
            </div>'
        }
<div id="app-1">
    <!-- 字面量绑定、动态绑定、动态绑定一个对象、动态绑定特例 -->
    <component-1 expect-msg="static data"
                 v-bind:expect-dynamic-msg="parentMsg" 
                 v-bind:expect-obj="parentObj" 
                 v-bind="parentObj">
    </component-1>
</div>

这里分别做了几种绑定的示例:vue

  • 把字符串"static data"绑定到子组件的propsexpectMsg
  • 把父组件属性parentMsg动态绑定到子组件的expectDynamicMsg特性上
  • 把父组件中的一个对象parentObj动态绑定到子组件的expectObj特性上
  • 把父组件中的parentObj对象的属性text、isShow绑定到子组件的textisShow特性上

注意:要下发一个数字给子组件不能使用字面量绑定,字面量下发的都是字符串。所以须要动态绑定java

<component v-bind:some-number="1">

Prop验证

当要对下发数据作验证或在无数据时设置默认值,子组件选项props就须要使用一个对象替换数组。
简单的状况:express

props:{
    someProp:String
}

下发数据必须是一个字符串数组

复杂点能够设置默认值与验证器,如:app

new Vue({
    el: '#app-2',
    data:{
        message:{
            title:'prop验证',
            text:'父组件数据'
        }
    },
    components: {
        'component-2': {
            props: {
                propObj:{
                    type:Object,
                    //下发对象的title属性必须是个字符串
                    validator:function(value){
                        return typeof value.title === "string"
                    },
                    //下发数据为一个数组或对象,设置的默认值必须由一个函数返回
                    default:function(){
                        return {title:'prop验证',text:'数组/对象的默认值应当由一个工厂函数返回'}
                    }
                }
            },
            template: '<div><h5>{{propObj.title}}</h5><p>{{propObj.text}}</p></div>'
        }
    }
})
<div id="app-2">
    <component-2 v-bind:prop-obj="message"></component-2>
</div>

type属性也能够是一个函数,使用instanceof验证。验证在子组件实例建立以前进行,所以验证里的任何函数都没法使用子组件实例属性。ide

更多类型验证 Prop验证函数

Prop的单向绑定和双向绑定

下发数据实际上就是完成一个数据绑定的过程,把组件间的特定数据绑定在一块儿,默认状况下为单向绑定,子组件的数据对于父组件是透明的,而父组件的数据变化则会引起子组件数据的变化。ui

new Vue({
    el: '#app-3',
    data: {
        content: "please input..."
    },
    components: {
        'component-3': {
            props:['txt'],
            template:'<div><input v-model="txt"></div>'
        }
    }
})
<div id="app-3">
    <input v-model="content">
    <br/>
    <component-3 v-bind:txt="content"></component-3>
</div>

clipboard.png

父组件经过Prop下发数据,将父组件属性content和子组件特性txt绑定在一块儿,在第一文本框输入值改变content的内容,子组件的txt会跟随变化,显示在第二个文本框中。

clipboard.png

若是在子模板第二个文本框输入,修改txt的值时,父组件控制的第一个文本框内容不会改变。

clipboard.png

并在控制台给出警告,说不要修改props选项中的值,做为代替,可让prop的值赋予data或者computed属性使用。所以能够像下面这样用data替代prop做为一个局部变量。

'component-3': {
    props:['txt'],
    template:'<div><input v-model="txtData"></div>',
    data:function(){
        return {txtData:this.txt}
    }
}

若只考虑输出不考虑输入,也可使用计算属性替代

'component-3': {
    props: ['txt'],
    template: '<div><input v-model="txtComputed"></div>',
    computed: {
        txtComputed:function() {
            return this.txt
        }
    }
}

非Prop特性

组件的做者却并不总能预见到组件被使用的场景。因此,组件能够接收任意传入的特性,这些特性都会被添加到组件的根元素上,而不须要定义响应的props

var vm = new Vue({  
    el: '#app-4',
    components: {  
        "component-4": {  
            template: "<button class='btn-sm'>hello vue!</button>"  
        }  
    }  
});
<div id="app-4">
    <component-4 data-title="learn vue" class="btn-info"></component-4>
</div>

渲染结果

<button class="btn-sm btn btn-info" data-title="learn vue">hello vue!</button>

其中data-titleclass就是非Prop特性。
由于没有在组件中定义props,所以也没法去引用它们,做用目前不明显。

从渲染结果还能够发现,class特性的值由子组件模板和父模板定义的特性合并而成,对于classstyle是这样合并结果。但对于多数组件来讲,传递给组件的值会覆盖组件自己设定的值。

相关文章
相关标签/搜索