props验证与默认值,Vue的双向数据绑定,Vue组件父传子,子传父,兄弟通信

1. props验证与默认值

父props与子props是单向下行绑定:父级的props的值更新会流动到子组件中,但反过来却不行。
避免子组件意外改变父级组件的状态,导致数据流混乱。
每次父级组件发生更新时,子组件中所有的props都将会刷新为最新的值。
不能在子组件内部改变props,否则会导致浏览器控制台发出警告
子组件要修改时,用$emit调用自定义事件,父组件接到后由父组件修改
改变props的常用例子:

  1. 这个用来传递一个初始值;这个组件接下来希望将其作为一个本地的数据来使用,要定义一个本地属性用做初始值、

      props:['initialCounter'],
      data:function(){
      return{
      counter:this.initialCounter
      	}
      }
    
  2. 这个以一种原始的值传入且需要进行转换,定义一个计算属性

      props:['size'],
      computed:{
      normalizedSize:function(){
      return this.size.trim().toLowerCase()
      	}
      }
    

2. Vue的双向数据绑定

  1. 定义数据监听器Observer,能够对数据对象所有属性进行监听,数据有变动会获取新值并通知订阅者;
  2. 定义一个指令解析器Compile,对每个元素节点指令进行扫描,根据指令模板替换数据,以及绑定相应的更新函数;
  3. 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图;

Vue实现双向数据绑定主要采用:数据劫持结合“发布-订阅”模式的方式,通过Object.defineproperty()的set和get,在数据变动是发布消息给订阅者触发监听。

Vue组件父传子,子传父,兄弟通信

1. 父传子:(通过props实现)

  1. 在父组件中给子组件标签绑定一个属性,属性上挂载需要传递的值;

  2. 在子组件通过props[“自定义属性名”]来接受数据;

以下是三种方法,没用vue写,引入vue.js文件,以下是HTML代码:

<body>
    <div id="app">
        <child></child>
    </div>
    <script src="./vue.js"></script>//引入vue.js文件
    <script>
        const child = {
            // props: ['msg'], // 第一种方法
            inject: ['name', 'age', 'tel'],
            template:  `
                <div>
                    这是子组件
                    {{msg}} {{name}} -- {{age}} -- {{tel}}
                </div>
            `,
            data() {
                return {
                    msg: ''
                }
            },
            created() {
                // console.log(this.$parent.msg) // 第二种方法 不建议过多的使用
                // this.msg = this.$parent.msg
                console.log(this.name, this.age, this.tel)
            }
        }
        Vue.component('child', child)
        new Vue({
            provide: { // 第三种方法 开发高阶组件时建议使用
                name: "张三",
                age: 16,
                tel: 110
            },
            data:{
                msg: '这是要传递给子组件的数据'
            }
        }).$mount('#app')
    </script>
</body>

2. 子传父:(通过$emit实现)

  1. 在父组件中给子组件标签绑定一个自定义事件,给这个事件挂载需要调用的方法;

  2. 在子组件的方法通过this.$emit(“自定义事件名”)来调用这个方法;

以下是HTML代码:

<body>
    <div id="app">
        <child @senddata="getData"></child>
    </div>
    <script src="./vue.js"></script>
    <script>
        const child = {
            template:  `
                <div>
                    这是子组件
                    <button @click="sendData">点击传递数据给父组件</button>
                </div>
            `,
            data() {
                return {
                    msg: '这是要传递给父组件的数据'
                }
            },

            methods: {
                sendData() {
                    this.$emit('senddata', this.msg)
                }
            }
        }
        Vue.component('child', child)
        new Vue({
            data:{
                msg: ''
            },
            mounted() {
                console.log(this.$children[0].msg)
            },
            methods: {
                getData(data) {
                    console.log(data)
                }
            }
        }).$mount('#app')
    </script>
</body>

3. 兄弟传参:两种方法

  1. 通过event bus实现

创建一个空的vue实例eventBUS,作为公共的桥梁;在两个组件中引入创建的bus,组件A用BUS.$ emit(“自定义事件名”,要传递的值)发送数据;组件B用BUS.$on(“自定义事件名”,function(v){挂载从A穿过来的数据})来接受数据

以下是HTML代码:

  <body>
    <div id="app">
      <child1></child1>
      <child2></child2>
    </div>
    <script src="./vue.js"></script>
    <script>
      const child1 = {
        template: `
                <div>
                    这是子组件
                    <button @click="send">点击传递数据给父组件</button>
                </div>
            `,
        data() {
          return {
            msg: "这是要传递给父组件的数据",
          };
        },

        methods: {
          send() {
            this.$bus.$emit("getdata", this.msg);
          },
        },
      };

      const child2 = {
        template: `
                <div>
                    这是子组件
                    {{msg}}
                </div>
            `,
        created() {
          // console.log(this)
          // var _this = this
          this.$bus.$on("getdata", (data) => {
            // console.log(this)
            this.msg = data;
          });
        },
        data() {
          return {
            msg: "",
          };
        },
      };
      Vue.component("child1", child1);
      Vue.component("child2", child2);
      var bus = new Vue();
      Vue.prototype.$bus = bus;
      new Vue({
        methods: {},
      }).$mount("#app");
    </script>
  </body>

2. 使用vuex来传递

vuex是一个状态管理工具,主要解决中大型复杂项目的数据共享数据

  1. State-存放Vuex store实例的状态对象,用于定义共享的数据。

  2. Action-动作,向store发出调用通知,执行异步操作。

  3. Mutations-修改器,它只用于修改state中定义的状态变量。

  4. getter-读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性)

  5. modules对state进行分类处理

流程:dispatch到actions,actions是异步操作,从commit到mutations

使用mutations再通过逻辑操作改变state,同步到组件,更新其数据状态。


版权声明:本文为L990614原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。