Kelichao / vue.js.2.0

针对vue2.0版本,以及关于MVVM框架学习,使用中的总结,附带backbone.js框架的思想与使用方法做使用记录,以及去年学过的backbone相关MVC框架学习总结与demo笔记思想设计模式 20170-01-12
40 stars 6 forks source link

【vue】组件的使用(2)Prop依赖,以及.sync用法 #18

Open Kelichao opened 7 years ago

Kelichao commented 7 years ago

组件间传递数据-prop

一、使用props传递字符串(等号形式)

<div id="aaa">
        <child message="hello!"></child>
</div>
    // 实例化
    new Vue({
        el:"#aaa",
        components: {
            'child': {
                    // 普通传入字符串方式
                    // 注意,单纯的等号只能传递字符串!
                    // 模板为<child message="hello!"></child>
                    // 就像 data 一样,prop 可以用在模板内,效果类似,只是从外部拿
                    props: ['message'],// message为数据名,template以此为参照
                    template: '<span>{{ message }}</span>'
            }
        }
    });

二、动态Props绑定使用(v-bind)

类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件,但子组件无法直接修改父组件的数据。

注意如果在别的模板中重复累加, 可能会导致动态渲染失效,但是首次渲染有效

三、字面量语法与动态语法

<!-- 传递了一个字符串"1" -->
<comp some-prop="1"></comp>
<!-- 传递实际的数字 -->
<comp v-bind:some-prop="1"></comp>

四、在prop中使用驼峰法的注意点

    // 当使用组件做模板时(即非字符串模板)
    // prop的名字形式会从 camelCase(驼峰法) 转为 kebab-case(短横线隔开)
    // 原因是html元素属性名统一会当做小写处理,渲染时为<span mymessage="hello!"></span>
    new Vue({
        el:"#aaa",
        components: {
            'child': {
                    // 使用prop时自动复原
                    props: ['upperData'],
                    template: '<span>{{ upperData.myMessage }}</span>'
            }
        }
    });

五、单向数据流

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。

另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。

<div id="aaa">
<child v-bind:message="parentMsg"></child>
</div>
// 实例化
a = new Vue({
el:"#aaa",
components: {
'child': {
// 普通传入字符串方式
// 注意,单纯的等号只能传递字符串!
// 模板为<child message="hello!"></child>
props: ['message'],// message为数据名,template以此为参照
template: '<span v-on:click="changeFather">{{ message }}</span>',
methods: {
changeFather: function() {
this.message = 0
}
}
}
},
data: {
parentMsg: "111111"
}
});

如果改变了这个值,是不会影响父组件的,但是vue会发出警告

default

推荐的方式是

// 实例化
a = new Vue({
    el:"#aaa",
    components: {
        'child': {
                // 普通传入字符串方式
                // 注意,单纯的等号只能传递字符串!
                // 模板为<child message="hello!"></child>
                props: ['message'],// message为数据名,template以此为参照
                template: '<span v-on:click="changeFather">{{ counter }}</span>',
                methods: {
                    changeFather: function() {
                        this.counter = 0;// 点击只改变自身内部属性
                    }
                },
                data: function () {
                    // 将props传入的数据通过闭包的形式传一次给组件内部的变量
                  return { counter: this.message }
                }
        }
    },
    data: {
        parentMsg: "111111"
    }
});

如果需要父子组件双向数据绑定, 特殊修饰符.sync

        <div id="aaa">
            <child v-bind:message.sync="parentMsg"></child>
        </div>
// 实例化
a = new Vue({
    el:"#aaa",
    components: {
        'child': {
                // 普通传入字符串方式
                // 注意,单纯的等号只能传递字符串!
                // 模板为<child message="hello!"></child>
                props: ['message'],// message为数据名,template以此为参照
                template: '<span v-on:click="changeFather">{{ message }}</span>',
                methods: {
                    changeFather: function() {
                        this.$emit('update:message', 12345)
                    }
                }
        }
    },
    data: {
        parentMsg: "111111"
    }
});

Prop中的类型验证

Vue.component('example', {
  props: {
    // 基础类型检测 (`null` 意思是任何类型都可以)
    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 value > 10
      }
    }
  }
})
isaaxite commented 6 years ago

其实直接将props绑定到data属性也是有个问题。就是父组件传入的值不会响应到子组件的HTML中,虽然子组件中基于props的data属性(如你例子中的counter)的值改变了,但是绑定在html中的counter不会响应式改变!如果想要有响应,就需要用计算属性,或者用watch监听props属性(例子中的message)的变化,然后再手动改变counter

kid1412621 commented 6 years ago

为什么我用 .sync ,在子组件修改 props 的值,Vue.js devtools里还是报错呢? UPDATE: 我弄错了, .sync 要写在子组件里