vue-系统学习.3

13.父组件和子组件

  组件与组件之间存在层级关系,如下构造父组件与子组件

<body>
    <div id="text">
        <!-- 使用父组件 -->
        <father_cnp></father_cnp>
    </div>

    <script src="../js/vue.js"></script>
    <script>
        //构造子组件构造器
        //注意这里需要先构造子组件构造器
        const cnp2 = Vue.extend({
            template: `<div><h2>vue子组件</h2></div>`
        })

        //构造父组件构造器
        const cnp1 = Vue.extend({
            template: `<div>
                <h2>vue父组件</h2>
                <son_cnp></son_cnp>
                </div>
            `,
            //在父组件构造器中注册子组件
            components: {
                son_cnp: cnp2
            }
        })
        var em = new Vue({
            el: '#text',
            data: {
                message: 100
            },
            //注册父组件
            components: {
                father_cnp: cnp1
            }

        })
    </script>
</body>

运行结果:

2.注册组件语法糖

 不需要使用extend构造组件构造器,使用如下方法注册(全局组件),

Vue.component('cpn',{
            template: `<div>
                <h2>这是一个组件</h2>
                </div>`
        })

 

省略extend,(其实vue已经帮我们构造好了)

与data同级注册局部组件(省略extend)

var em = new Vue({
            el: '#text',
            data: {
                message: 100
            },
            //注册局部组件
            components: {
                'cpn3': {
                    template: `<div>
                <h2>这是一个私有组件</h2>
                </div>`
                },
            }

        })

组件能否访问vue实例中data的数据

!不能直接访问,vue组件有自己存储数据的地方

!组件对象里面也有一个data属性(也可以有methods等属性),只是这个data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存数据

当data属性为一个函数时,各个组件调用data中的数据是不会相互影响的,

例如:

<body>

  <div id="text">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>1.当前计数{{sum}}</h2>
      <button @click="add">+1</button>
      <button @click="sub">-1</button>
    </div>
  </template>

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

    Vue.component('cpn', {
      template: '#cpn',
      data() {
        return {
          sum: 0
        }
      },
      methods: {
        add() {
          this.sum++
        },
        sub() {
          this.sum--
        }
      }

    }

    )

    var em = new Vue({
      el: '#text',
      data: {
        message: 100
      },

    })

  </script>

</body>

运行结果如下,当你点击每一个组件计数器时是不会影响其他组件计数器的值的

但是当你这样定义data时,各个组件调用data中数据时会产生连锁反应,

例如:

<body>

  <div id="text">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>1.当前计数{{sum}}</h2>
      <button @click="add">+1</button>
      <button @click="sub">-1</button>
    </div>
  </template>

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

    const obj ={
      sum:0
    }

    Vue.component('cpn', {
      template: '#cpn',
      data() {
       return obj
      },
      methods: {
        add() {
          this.sum++
        },
        sub() {
          this.sum--
        }
      }

    }

    )

    var em = new Vue({
      el: '#text',
      data: {
        message: 100
      },

    })

  </script>

</body>

 

运行结果如下,当你点击一个组件计数器时,会同时影响其他组件计数器数据,产生连锁反应!!!

14.父子组件传值

  1. 父向子传值

父组件通过props向子组件传递数据

例子:

 

<body>

  <div id="text">
//v-bind绑定传递过来的数据名,用子组件定义的数据名进行接收
    <cpn v-bind:sonmessage="message"></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>父向子组件传递的数据为:{{sonmessage}}</h2>
    </div>
  </template>

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

    //子组件
    const cpn = {
      template: "#cpn",
      props: ['sonmessage'],
      data() {
        return {}
      }
    }
    //root组件(父组件)
    var em = new Vue({
      el: '#text',
      data: {
        message: '你好'
      },
      components: {
        cpn
      }

    })

  </script>

</body>

运行结果:

Props不仅仅可以是数组的形式,还可以是对象的形式

例如:

props:{

Sonmessage: string  //限制传递过来的数据的类型

default: ‘aaa’    //默认值,当传递过来的数据为空时,则采取默认值

require: true    //当require为true时,限制必须传递数据,否则报错

}

当需要对数据类型进行验证时,就需要props对象类型了,可以验证的类型有

  1. string
  2. array
  3. Boolean
  4. Object
  5. Date
  6. Number
  7. Function
  8. Symbol

注意:通过props接收的数据不推荐直接在子组件中进行修改,(或者说通过props接收的数据为只读数据)

  1. 子向父传值

子组件通过自定义事件向父组件传递数据

在子组件中通过$emit来触发事件,父组件通过v-on来监听子组件事件

<body>

  <div id="text">
    <!-- 父组件接收子组件传递的数据 -->
    <cpn @sentdata="receivedata"></cpn>
  </div>

  <template id="cpn">
    <div>
      <button v-for="item in category" @click="btnclick(item)">{{item.name}}</button>
    </div>
  </template>

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

    //子组件向父组件传递数据
    const cpn = {
      template: "#cpn",

      data() {
        return {
          category: [
            { id: "a", name: "海贼王" },
            { id: "b", name: "火影忍者" },
            { id: "c", name: "死神" }
          ]
        }
      },
      methods: {
        btnclick(item) {
          //发射自定义事件
          this.$emit('sentdata', item)
        }

      }
    }
    //root组件(父组件)
    var em = new Vue({
      el: '#text',
      data: {
        message: '你好'
      },
      components: {
        cpn
      },
      //接收子组件通过自定义事件传递过来的值
      methods: {
        receivedata(item) {
          console.log('receivedata', item);
        }
      }

    })

  </script>

</body>

 3.

父子组件访问

父组件通过$refs 访问子组件

<body>
  <div id="text">
<cpn ref="aaa"></cpn>
<button @click="btnclick">父访问子组件</button>
  </div>

  <template id="cpn">
    <div>
      <h2>这是一个子组件</h2>
    </div>
  </template>

  <script src="js/vue.js"></script>
  <script>
    var em = new Vue({
      el: '#text',
      data: {
        message: '你好'
      },
      methods: {
  btnclick(){
//打印子组件内容
    console.log(this.$refs);
  }
      },
      components : {
        cpn: {
          template: "#cpn"
        }
        
      }

    })

  </script>
</body>

打印结果

子访问父组件

子组件通过this.$parent访问父组件(距离最近的子组件)

访问根组件

    通过this.$root访问根组件vue实例

15.watch监听器:监听数据变化并作出反应

语法格式:

watch: {

数据名称(newvalue,oldvalue){

事件}

16.插槽slot

插槽的目的是让我们原来的设备具备更多的扩展性

组件的插槽让我们封装的组件更加有扩展性,一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容

例子:

 

<body>
  <div id="text">
<cpn>
  <button>第一个组件使用插槽</button>
</cpn>
<cpn>
  <input type="text" value="第二个组件使用插槽" id="">
</cpn>
<cpn>
  <p>第三个组件使用插槽</p>
</cpn>
<!-- 第四个组件没有使用预留插槽 -->
<cpn></cpn>

  </div>

  <template id="cpn">
    <div>
      <h2>这是一个子组件</h2>
      <!-- 预留插槽 -->
      <slot></slot>
    </div>
  </template>

  <script src="js/vue.js"></script>
  <script>
    var em = new Vue({
      el: '#text',
      data: {
        message: '你好'
      },
      
      components : {
        cpn: {
          template: "#cpn"
        }
        
      }

    })

  </script>
</body>

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值