父子组和插槽

105 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

一。父子组件

image.png 1.子组件访问父组件数据

   <div class="root">
  <div class="a">
    <p>姓名:{{name}}</p>
    <p>年龄:{{age}}</p>
    <!-- 子组件 -->
    <b-box></b-box>
  </div>
</div>
<script src="./js/vue.min.js"></script>
<script>
  Vue.config.productionTip = false;
//   子组件
  Vue.component("b-box", {
    template: `
      <div class="b">
        <p>姓名:{{names}}</p>
        <p>年龄:{{ages}}</p>
        <button @click="changename">点我修改姓名</button>
      <button @click="changeage">点我修改年龄</button>
      </div>
      `,

    data() {
      return {
        names: "",
        ages: 0,
      };
    },
    // 挂载完成
    mounted() {
      this.names = this.$parent.name;
      this.ages = this.$parent.age;
    },

this.parent.agethis指的是bbox组件,parent.age this指的是b-box组件,parent指的是父亲

    methods: {
      changeage() {
        this.ages = 30;
        this.$parent.age = this.ages;
    },
      changename() {
        this.names = "李小龙";
        this.$parent.name = this.names;
      },
    },
  });
  new Vue({
    el: ".root",
    data: {
      name: "赵露思",
      age: 20,
    },
  });
  星冰乐  18:23:13

修改前

image.png

修改后

image.png

2.父组件访问子组件数据

   <div class="root">
  <div class="a">
    <b-box></b-box>
    <input type="text" v-model="fruit">
    <button @click="add">点我添加水果</button>
  </div>
</div>
<script src="./js/vue.min.js"></script>
<script>
  Vue.config.productionTip = false;
  //   子组件
  Vue.component("b-box", {
    template: `
    <ul class="b">
        <li v-for="(item,index) in fruits" :key="index">{{item}}</li>
    </ul>
      `,
    data() {
      return {
        fruits: ["香蕉", "葡萄", "苹果", "榴莲"],
      };
    },
  });
  new Vue({
    el: ".root",
    data: {
        fruit:""
    },
    methods: {
        add(){

this指的是vue实例,$children指的是他的孩子,他的孩子可以有很多个,是一个数组,所以选取第一个,也就是下标为0

           this.$children[0].fruits.push(this.fruit)
        }
    },
  });
  

image.png 二。插槽

1.什么是插槽

       在开发中,我们会经常封装一个个可复用的组件,前面我们会通过props传递给
       组件一些数据,让组件来进行展示,但是为了让这个组件具备更强的通用性,我
       们不能将组件中的内容限制为固定的divspan等等这些元素,比如某种情况下
       我们希望组件显示的是一个按钮又或者某种情况下我们使用组件希望显示的是一
       张图片,因此我们应该让使用者去决定某一块区域到底存放什么内容。
       
       

①。使用前

image.png

②。使用后

         template: `
    <div class="box">
    <div class="box_a">{{title}}</div>
    <div class="box_b">
        {{contenta}}
        <slot></slot>
        </div>
   
  </div>
      `,

image.png 2.具名插槽( 当插槽有两个及两个以上的时候需要给插槽name,搭配template使用,且template里面需要加v-slot:name或者#name)

           <div class="root">
  <b-box>
    <template v-slot:box_a> 华为手机 </template>
    <template v-slot:box_b>
      <p>华为手机很好用</p>
      <p>
        <img
          src="https://img1.baidu.com/it/u=1506634078,1185354152&fm=253&fmt=auto&app=138&f=JPEG?w=747&h=500"
          alt=""
        />
      </p>
    </template>
    <template #box_c>
      <p>联系电话:123952852</p>
      <p>公司邮箱:743846@43.com</p>
    </template>
  </b-box>
</div>
<script src="./js/vue.min.js"></script>
<script>
  Vue.config.productionTip = false;
  //   子组件
  Vue.component("b-box", {
    //   当插槽有两个及两个以上的时候需要给插槽name,搭配template使用,且template里面需要加v-slot:name或者#name
    template: `
    <div class="box">
      <div class="box_a">
           <slot name="box_a"></slot>
      </div>
      <div class="box_b">
           <slot name="box_b"></slot>
      </div>
      <div class="box_c">
           <slot name="box_c"></slot>
      </div>
  </div>
      `,
    props: ["title", "contenta"],
  });
  new Vue({
    el: ".root",
    data: {
     
    },
  });
</script>

image.png 3.作用域插槽(作用域插槽是子组件可以在slot标签上绑定属性值,在父组件可以拿到子组件的数据,通过子组件绑定数据传递给父组件。(插槽的作用域为子组件))

         <div class="root">
  <b-box>
      <!-- slot绑定的数据储存在#edit="box"的box里面 -->
    <template #edit="box">
      <button @click="del(box)">删除</button>
    </template>
    <template #deit_a="boxa">
      id:<input type="text" v-model="car.id" />
      <br />
      name:<input type="text" v-model="car.name" />
      <br />
      price:<input type="text" v-model="car.price" />
      <br />
      <button @click="add(boxa)">添加</button>
    </template>
  </b-box>
</div>
<script src="./js/vue.min.js"></script>
<script>
  Vue.config.productionTip = false;
  //   子组件
  Vue.component("b-box", {
    template: `
    
      <ul class="box_a">
        <li class="box_b" v-for="(item,index) in cars" :key="item.id">
            {{item.id}}--{{item.name}}--{{item.price}}
        <slot name="edit" :index="index" :list="cars"></slot>
        </li>
        <slot name="deit_a" :list="cars"></slot>
      </ul>
      
  
      `,
    data() {
      return {
        cars: [
          {
            id: 1,
            name: "奔驰",
            price: "50w",
          },
          {
            id: 2,
            name: "宝马",
            price: "40w",
          },
          {
            id: 3,
            name: "奥迪",
            price: "30w",
          },
          {
            id: 4,
            name: "大众",
            price: "20w",
          },
        ],
      };
    },
  });
  new Vue({
    el: ".root",
    data: {
      car: {
        id: 0,
        name: "",
        price: "",
      },
    },
    methods: {
        // 解构box里的内容
      del({ index, list }) {
        console.log(index, list);
        if (confirm("你确定删除吗")) {
          list.splice(index, 1);
        }
      },
        // 解构boxa里的内容
      add({ list }) {
        console.log(list);
        list.push(this.car);
      },
    },
  });
</script>

image.png

image.png