388 vue 之 props: 只读,prop的大小写,prop的类型,prop的校验

十、props 的特点 : 只读

  • 演示验证 props 只读
    • 传的是简单类型 : 修改会报错
    • 传的复杂类型 (地址) : 修改不会报错,是因为地址没有变 ,测试 obj={}立马报错 【修改对象中的数据,不会修改对象的地址,但是修改对象的地址就报错。】
  • 修改父组件传给子组件的数据

思路 : 把接收过来的数据,保存到 data 中一个临时值 (适用在该组件接收数据只会在当前组件内使用)

  Vue.component('child', {
        template: `
      <div>子组件 {{ cmsg }} </div>
       `,
        data() {
          return {
            cmsg: this.msg
          }
        },
        props: ['msg'],
        created() {
          this.cmsg = 666
        }
      })

完善TodoMVC => 修改状态 + 修改任务


08-prop的只读特性.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <div id="app">
        <child :msg="pmsg" :obj="pobj"></child>
    </div>

    <script src="./vue.js"></script>
    <script>
        Vue.component('child', {
            template: `
                <div> 子组件 : {{ obj.name }}</div>
            `,
            props: ['msg', 'obj'],
            mounted() {
                // 修改传递过来的数据
                // 1. 修改基本类型的数据,报错
                // this.msg = 666 

                //2. 只是改了对象里的内容 ,并没有改地址
                // this.obj.name = '春春'   // 虽然这不会报错,但是也不要这么改
                this.obj = {} // 这样写报错
            }
        })

        const vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父的信息',
                pobj: {
                    name: '张三'
                }
            }
        })
    </script>
</body>

</html>

补充的案例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <one :msg="pMsg" :obj="pObj"></one>
  </div>

  <script src="./vue.js"></script>

  <script>
    Vue.component('one', {
      template: `
        <div>
          <div>{{msg}} - {{obj.name}}</div>
          <div>{{cMsg}} - {{cObj.name}}</div>
        </div> `,
      data() {
        return {
          // 把接收过来的数据,保存到 data 中一个临时
          cMsg: this.msg,
          cObj: this.obj
        }
      },
      props: ['msg', 'obj'],
      created() {
        this.cMsg = 333
        this.cObj.name = '嘻嘻'
        this.cObj = { name: '嘿嘿' }
      },
    })

    const vm = new Vue({
      el: '#app',
      data: {
        pMsg: '111',
        pObj: {
          name: '哈哈'
        }
      }
    })
  </script>
</body>

</html>


十一、prop 的大小写

  • 官 : HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。

    • html 的标签和 属性 都是一样,忽略大小写
    • <H1 TITLE="哈哈">我是h1</H1>
  • 官 : 这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名不好使了

    • <child :cMsg="pmsg"></child> 会报警告,父传子也接收不到了
    • 原因是 : 接收的属性是:cMsg, 因为忽略大小写,已为 : cmsg
    • 所以已经准备要读取的 是 cmsg 的值,否则要报警告
      You should probably use "c-msg" instead of "cMsg".
  • 方式 1 : 全用小写,不要使用驼峰命名 (不推荐)

    • 接收 : cmsg
    • props/读取 :cmsg
  • 方式 2 官 : 需要使用其等价的 kebab-case (短横线分隔命名) 命名: (推荐)

    • 接收 : :c-msg='pmsg'
    • props/读取 : cMsg / this.cMsg
  • 大小写在 父传子和 子传父中的应用 (都是要 带 - 的)

    • 父传子 : :c-msg ==> cMsg 改驼峰 - 因为props
    • 子传父 : @todo-head = 'pAddTodo' ==> this.$emit('todo-head') 不改驼峰
  • 完善 TodoMVC : 底部隐藏+剩余完成数+清除完成

    • 计算属性 : 已知值(todoList 在 根组件) ==> 得到一个新值(子组件里使用)
    • 父 => 子通讯
  • 番外篇 : 方法当属性传、传过来的带:得到的原型


09-prop的大小写问题.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <!-- 
       原因 :
       1. cMsg  => cmsg

       解决办法 :
       1. 用小写 (不推荐)
       2. 短横线分割符
         赋值   :c-msg='pMsg'
               -删除掉 -后面的首字母变大写 cMsg
         指定 : cMsg
         使用 : cMsg
     -->
    <div id="app">
        <child :c-msg="pMsg" :c-user-name="pUserName"></child>
    </div>

    <script src="./vue.js"></script>
    <script>
        Vue.component('child', {
            template: `
                <div> 子组件 : {{ cMsg }}  {{ cUserName }} </div>
             `,
            props: ['cMsg', 'cUserName']
        })

        const vm = new Vue({
            el: '#app',
            data: {
                pMsg: '父的信息',
                pUserName: '大傻春'
            }
        })
    </script>
</body>

</html>

10-大小写问题应用在子传父和父传子.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <!-- 
       (prop的)大小写问题 【是prop的大小写问题,不是事件的。 】
       1. 父传子  c-msg  =>  cMsg
       2. 子传父 @add-todo   ==> add-todo
     -->
    <div id="app">
        <child :c-msg="pMsg" @add-todo="pAddTodo"></child>
    </div>

    <script src="./vue.js"></script>
    <script>
        Vue.component('child', {
            template: `
                <div> 子组件 :  {{ cMsg }} </div>
            `,
            props: ['cMsg'],
            created() {
                this.$emit('add-todo')
            }
        })

        const vm = new Vue({
            el: '#app',
            data: {
                pMsg: '父的信息'
            },
            methods: {
                pAddTodo() {
                    console.log('哈哈')
                }
            }
        })
    </script>
</body>

</html>

11-prop的类型问题.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <!-- 
       1. 通过prop 赋值的时候, 如果直接赋值一个静态值, 不管是什么值, 都是字符串类型
        'abc' / '123' / 'true'
       2. 在 属性前面加一个冒号“:” , 可以获取它的真实类型

        总结 :
        1.  :msg='pmsg/动态值/data里属性'  
        2.  :msg='固定值/静态值' : 读取固定值的真实类型,赋值给 msg    

     -->

    <div id="app">
        <child :msg="true" :na="name"></child>
    </div>

    <script src="./vue.js"></script>
    <script>
        Vue.component('child', {
            template: `
            <div> 子组件 :  </div>
           `,
            props: ['msg'],
            created() {
                // 'abc'  => 字符串
                // '123'  => '123' 字符串
                console.warn(this.msg, typeof this.msg) // true "boolean"
                console.warn(this.na, typeof this.na) // 123 "number"
            }
        })

        const vm = new Vue({
            el: '#app',
            data: {
                name: 123
            }
        })
    </script>
</body>

</html>

12-类型的校验问题.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>

<body>
    <div id="app">
        <!-- 大傻春拿去用了 -->
        <!-- <child :msg="111"></child> -->
        <child></child>
    </div>
    <script src="./vue.js"></script>
    <script>
        // 这个组件是我注册的
        Vue.component('child', {
            template: `
        		<div> 子组件 :  </div>
          	`,
            props: ['msg'],

            // props: {
            //   msg: Number // 仅仅是告诉其类型
            // },
            // props: {
            //     msg: {
            //         type: Number, // 类型
            //         default: 100 // 默认值
            //     }
            // },
            created() {
                // 我希望的是一个数字类型
                console.log(this.msg, typeof this.msg)
                console.log(this.msg + 10) // 133
            }
        })

        const vm = new Vue({
            el: '#app',
            data: {}
        })
    </script>
</body>

</html>

<!-- 
   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
      }
    }
  }
})
 -->
原文地址:https://www.cnblogs.com/jianjie/p/12529424.html