深入了解Vue组件 — Prop(下)

1.4 单向数据流

所有的prop都是从父组件传递到子组件中,反过来则不行。
每次父组件发生更新时,子组件中的所有prop都将会刷新为最新的值。
我们不应该在子组件内部改变prop。
两种常见的试图改变prop的情形:
① 这个prop用来传递一个初始值;这个子组件将其作为一个本地的prop数据来使用。
② 传入的这个prop需要进行转换。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">      
        <style>
            
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
        <div id="app">
			<my-component v-bind:initial-counter="counter"></my-component>			
			<button @click="addOne">加1</button>
			<p>{{ counter }}</p>
        </div>
        <script>
            Vue.component('my-component', {
              props: ['initialCounter'],
			  data: function(){
				return {
					counter: this.initialCounter
				}
			  },
              template: '<div><p>{{ counter }}</p><p>{{ initialCounter }}</p></div>'
            })
            
            new Vue({
                el: '#app',
                data: {
					counter: 42
                },
				methods: {
					addOne: function(){
						this.counter++
					}
				}
            });
        </script>
    </body>
</html>


使用计算属性:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">      
        <style>
            
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
        <div id="app">
			<my-component size="BiG"></my-component>			
        </div>
        <script>
            Vue.component('my-component', {
              props: ['size'],
			  computed: {
				normalizedSize: function () {
					return this.size.trim().toLowerCase()
				}
			  },
              template: '<div><p>{{ normalizedSize }}</p></div>'
            })
            
            new Vue({
                el: '#app',
                data: {
					
                }
            });
        </script>
    </body>
</html>

1.5 Prop验证

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>

    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <my-component v-bind="post"></my-component>
</div>
<script>
    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
                }
            }
        },
        template: '<div><p>{{ propD }}</p><p>{{ propE.message }}</p></div>'
    })

    new Vue({
        el: '#app',
        data: {
            post: {
                propA: '42',
                propB: {name: 'Hjj'},
                // propC: ''
                // propD: 0,
                // propE: {},
                propF: 'false'
            }
        }
    });
</script>
</body>
</html>

1.5.1 类型验证

type可以是下列原生构造函数中的一个:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

type还可以是一个自定义的构造函数。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>

    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <my-component v-bind:author="person"></my-component>
</div>
<script>
    Vue.component('my-component', {
        props: {
            author: Person
        },
        template: '<div><p>{{ typeof author }}</p><p>{{ author.firstName }}</p><p>{{ author.lastName }}</p></div>'
    });

    new Vue({
        el: '#app',
        data: {
            person: new Person('He', 'jiajun')
        }
    });

    function Person (firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
</script>
</body>
</html>

1.6 非 Prop 的特性

一个非 prop 特性是指传向一个组件,但是该组件并没有相应 prop 定义的特性。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">      
        <style>
            .parentClass {
				background: orange
			}
			.childClass {
				padding: 5px;
			}
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
        <div id="app">
			<my-component class="parentClass"></my-component>			
        </div>
        <script>
			Vue.component('my-component', {
				props: {
					
				},
				template: '<div class="childClass">Hello</div>'
			})
            
            new Vue({
                el: '#app',
                data: {
					
                }
            });
        </script>
    </body>
</html>

1.6.1 禁用特性继承

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>

    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <form>
        <base-input label="Username: "
                    v-bind:value="username"
                    v-on:input="username = $event"
                    required placeholder="Enter your username"></base-input>
        <br/>
        <p>{{ username }}</p>
    </form>
</div>
<script>
    Vue.component('base-input', {
        props: ['label', 'value'],
        template: `<label>{{ label }}
		<input v-bind:value="value" v-on:input="$emit('input', $event.target.value)"></label>`
    });

    new Vue({
        el: '#app',
        data: {
            username: ''
        }
    });
</script>
</body>
</html>


解释:组件的requiredplaceholder被继承到根元素<label>;组件的labelvalue作为prop传递。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>

    </style>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <form>
        <base-input label="Username: "
                    v-bind:value="username"
                    v-on:input="username = $event"
                    required placeholder="Enter your username"></base-input>
        <br/>
        <p>{{ username }}</p>
    </form>
</div>
<script>
    Vue.component('base-input', {
        inheritAttrs: false,
        props: ['label', 'value'],
        template: `<label>{{ label }}
		<input v-bind="$attrs" v-bind:value="value" v-on:input="$emit('input', $event.target.value)"></label>`
    });

    new Vue({
        el: '#app',
        data: {
            username: ''
        }
    });
</script>
</body>
</html>


解释:inheritAttrs: false这里的作用是不让根元素<label>继承requiredplaceholderv-bind="$attrs"这里的作用是让<input>继承requiredplaceholderlabelvalue仍然作为prop传递。

参考:

posted @ 2021-01-21 16:49  gzhjj  阅读(305)  评论(0编辑  收藏  举报