10-Vue之Prop

Prop 的大小写 (camelCase vs kebab-case)

HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名。重申一次,如果你使用字符串模板,那么这个限制就不存在了。

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase(驼峰命名法) 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case(短横线命名法) 的 -->
<blog-post post-title="hello!"></blog-post>

这里,组件中的props的属性值是用的驼峰命名法,html中的属性名必须是短横线命名法。

传递静态或动态 Prop

给 prop 传入一个静态的值:

<blog-post title="My journey with Vue"></blog-post>

prop 可以通过 v-bind 动态赋值

<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
  v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>

实际上任何类型的值都可以传给一个 prop。

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>单向数据流</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    </head>
        <div id="app">
            <custom-component :count="count"></custom-component>
        </div>
       
    <body>
        
    </body>
    <script src="js/vue.js"></script>
    <script type="text/javascript">
       Vue.component('custom-component',{
           props: ['count'],
           template: `
                <div>
                    <h3>这是一个自定义模板</h3>
                    <input type="button" value="按钮" @click="changeCount" />
                    <p>{{count}}</p>
                </div>
           `,
           methods: {
               changeCount(){
                   this.count++
               }
           }
       })
       var app = new Vue({
           el: '#app',
           data () {
               return{
                   count: 0
               }
           }
       })
    </script>
</html>

数据从父级组件传递给子组件,只能单向绑定。子组件内部不能直接修改从父级传递过来的数据。
上面代码控制台会出现报错:避免在子组件数据被重写,可以改变props的情况,使用数据或计算属性来解决。

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>单向数据流</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    </head>
        <div id="app">
            <custom-component :count="count"></custom-component>
        </div>
       
    <body>
        
    </body>
    <script src="js/vue.js"></script>
    <script type="text/javascript">
       /* Vue.component("custom-component", {
            //作为data中局部数据的初始值来过渡,必须以函数形式申明,
            //相当于子组件里操作的都是this.count的指针
            data() {
                return {
                    initCount: this.count
                }
            },
            props: ['count'],
            template: `
            <div>
                <h1>一个自定义模版</h1>
                <input type="button"  @click="changeCount" value="按钮"/>
                {{initCount}}
            </div>`,
            methods: {
                changeCount() {
                  //这里计算的也是initCount
                    this.initCount++
                }
            }
        }); */

        Vue.component("custom-component", {
            data() {
                return {
                    initCount: this.count
                }
            },
            //与直接使用data不同的是这里添加选项参数计算属性`computed`
            computed: {
                initCount2() {
                    return this.initCount;
                }
            },
            props: ['count'],
            template: `
            <div>
                <h1>一个自定义模版</h1>
                <input type="button"  @click="changeCount" value="按钮"/>
                {{initCount2}}
            </div>`,
            methods: {
                changeCount() {
                    this.initCount++
                }
            }
        });

       var app = new Vue({
           el: '#app',
           data () {
               return{
                   count: 0
               }
           }
       })
    </script>
</html>

Prop 验证

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。
为了定制 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
      }
    }
  }
})

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。

类型检查

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

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
    额外的,type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。

禁用特性继承

如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false。例如:

Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • 什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装...
    youins阅读 9,478评论 0 13
  • 此文基于官方文档,里面部分例子有改动,加上了一些自己的理解 什么是组件? 组件(Component)是 Vue.j...
    陆志均阅读 3,825评论 5 14
  • 组件(Component)是Vue.js最核心的功能,也是整个架构设计最精彩的地方,当然也是最难掌握的。...
    六个周阅读 5,603评论 0 32
  • 一、什么是组件(Component)? 组件(Component)是Vue.js最强大的功能之一。组件可以扩展HT...
    廖马儿阅读 24,283评论 1 4
  • 什么是组件 组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用...
    angelwgh阅读 783评论 0 0