插槽传递数据

在使用element-ui的时候我们会经常用到插槽。

1.element-ui里面的插槽语法

如:一个dialog组件

代码:

<template>
  <div class="">
    <el-button type="text" @click="dialogVisible = true"
      >点击打开 Dialog</el-button
    >

    <el-dialog
      title="提示"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handleClose"
    >
      <span>这是一段信息</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialogVisible: false,
    };
  },
  methods: {
    handleClose(done) {
      this.$confirm("确认关闭?")
        .then(() => {
          done();
        })
        .catch(() => {});
    },
  },
};
</script>

<style scoped></style>

slot='footer' 默认插槽

 <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >确 定</el-button
        >
      </span>

定义标题:

 这相当于一个传值的过程。

下拉菜单:

 代码:

<template>
  <div class="">
    <el-dropdown :hide-on-click="false">
      <span class="el-dropdown-link">
        下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>黄金糕</el-dropdown-item>
        <el-dropdown-item>狮子头</el-dropdown-item>
        <el-dropdown-item>螺蛳粉</el-dropdown-item>
        <el-dropdown-item disabled>双皮奶</el-dropdown-item>
        <el-dropdown-item divided>蚵仔煎</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
export default {
  name: "",
  methods: {},
};
</script>

<style scoped>
.el-dropdown-link {
  cursor: pointer;
  color: #409eff;
}
.el-icon-arrow-down {
  font-size: 12px;
}
</style>

这里面通过slot=‘dropdown’包裹着:

 同样也是使用了具名插槽。

2.插槽的种类与用法

什么是插槽?

我理解的就是占位。 举个例子来讲,我们去封装一个组件,这个组件被很多的页面同时用到,但是又有些甚微的差别,这个时候我们可以用插槽来解决此问题。

用图来表示:

假设这个头部的组件在很多的地方使用,但是标题 和内容不一样这个时候就插槽排上用场了。

插槽的种类和用法

种类

1.默认插槽  没名字插槽

2.具名插槽   用名字的插槽

3.作用域插槽   传递数据的插槽

用法

在此之前组件都是全局注册过的

在main.js

import One from "@/components/One.vue";
Vue.component(One.name, One);

1.默认插槽

直接在标签里面些东西。

传:

<template>
  <div class="">
    <One>123</One>
  </div>
</template>

收One组件:

<template>
  <div class="">
    <slot />
  </div>
</template>

2.具名插槽

传递:

<template>
  <One>
    <template #aa>
      <div>
        <button>增加</button>
        <button>删除</button>
      </div>
    </template>
  </One>
</template>

在这个One组件里面

占位:

<template>
  <div class="">
    <slot name="aa" />
  </div>
</template>

在当前封装的组件里面进行占位,传过来两个按钮。

3.作用域插槽

传递数据:

<template>
  <div class="">
    <slot :data="form" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: "张三",
        age: 20,
      },
    };
  },
  name: "One",
  methods: {},
};
</script>

<style scoped></style>

接收:

<template>
  <One>
    <template v-slot="row">
      <div>{{ row }}</div>
    </template>
  </One>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {},
};
</script>

<style scoped></style>

view:

可以看到已经传递过去了。

这一幕是不是很相似呢?

请看下面的图片:

 这里的slot-scope是2.60以前的写法2.60以后使用的是v-slot的写法,这是在表格里面使用的插槽。

3.案例   

我们全局注册一个组件:

注册的组件:

<template>
  <div class="pageTools">
    <div class="left">
      <i class="el-icon-info" />
      <slot name="left" />
    </div>
    <div class="right">
      <slot name="right" />
    </div>
  </div>
</template>

<script>
export default {
  // 组件的名字
  name: 'PageTools',
  props: {
    showLeft: {
      type: Boolean,
      default: true
    }
  },
  methods: {}
}
</script>

<style lang="scss" scoped>
.pageTools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 20px;
  .left {
    background-color: pink;
    border: 1px solid #91d5ff;
    display: flex;
    align-items: center;
    .el-icon-info {
      color: #409eff;
    }
  }
  .right {
    display: flex;
    align-items: center;
  }
}
</style>

  在main.js里面

import PageTools from '@/components/lib/pageTools.vue'
Vue.component(PageTools.name, PageTool

我们在一个页面通过插槽来使用自己的组件

代码:

<template>
  <div class="">
    <PageTools>
      <template #left>
        <div>
          <span>有10条记录</span>
        </div>
      </template>
      <template #right>
        <div>
          <el-button type="primary">新增</el-button>
          <el-button type="primary"> 删除</el-button>
        </div>
      </template>
    </PageTools>
  </div>
</template>

<script>
export default {
  name: '',
  methods: {}
}
</script>

<style scoped></style>

view图:

现在我们在使用的使用不需要左侧的

通过给组件的传值来控制组件的显示和隐藏。

代码:

<template>
  <div class="">
    <PageTools :show-left="false">
      <template #left>
        <div>
          <span>有10条记录</span>
        </div>
      </template>
      <template #right>
        <div>
          <el-button type="primary">新增</el-button>
          <el-button type="primary"> 删除</el-button>
        </div>
      </template>
    </PageTools>
  </div>
</template>

<script>
export default {
  name: '',
  methods: {}
}
</script>

<style scoped></style>

view图:

 为什么还是有背景色有边框的影响

解决:

<template>
  <div class="pageTools">
    <div class="left">
      <div v-if="showLeft" class="left-content">
        <i class="el-icon-info" />
        <slot name="left" />
      </div>
    </div>
    <div class="right">
      <slot name="right" />
    </div>
  </div>
</template>

<script>
export default {
  // 组件的名字
  name: 'PageTools',
  props: {
    // 默认有左边
    showLeft: {
      type: Boolean,
      default: true
    }
  },
  methods: {}
}
</script>

<style lang="scss" scoped>
.pageTools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 20px;
  .left {
    .left-content {
      background-color: #91d5ff;
      border: 1px solid #91d5ff;
      display: flex;
      align-items: center;
      .el-icon-info {
        color: #409eff;
      }
    }
  }
  .right {
    display: flex;
    align-items: center;
  }
}
</style>

通过包裹住一层盒子来解决问题。

4.默认插槽

别看默认插槽,里面还藏了很多的猫腻。

v-slot和#是一样的

v-slot:aa  表示为名字aa的插槽相对应。

如果v-slot啥也不写对应的就是v-slot:default,也就是对应的默认插槽。

代码:

<template>
  <div>
    <One #aa>aa插槽的内容</One>
    <One #cc>cc插槽的内容</One>
    <One>
      <template v-slot>
        <div>默认插槽的内容</div>
      </template>
    </One>
  </div>
</template>

<script>
export default {
  name: "",
  methods: {},
};
</script>

<style scoped></style>

One组件:

<template>
  <div class="">
    <slot name="default"></slot>
    <slot name="aa"></slot>
    <slot name="cc"></slot>
  </div>
</template>

<script>
export default {
  name: "One",
  methods: {},
};
</script>

<style scoped></style>

 仔细看#default就是通过默认 转化下就是v-slot:default 就是默认插槽。

那么通过作用域获取数据的两种方式:

1.默认的方式

v-slot=‘row’     v-slot:default=‘row’ 是等价的

2.具名的方式

v-slot:aa=row     等价于#aa=‘row’

代码:

<template>
  <div class="">
    <One>
      <template v-slot:default="row">
        <div>
          {{ row }}
        </div>
      </template>
    </One>
  </div>
</template>

<script>
export default {
  data() {
    return {
      age: 20,
    };
  },
  name: "",
  methods: {},
};
</script>

<style scoped></style>

<template>
  <div class="">
    <slot :data="form" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: "张三",
        age: 20,
      },
    };
  },
  name: "One",
  methods: {},
};
</script>

<style scoped></style>

因此我们平常在写v-slot=‘row’的时候其实v-slot:default=‘row’ 这两种都是默认插槽的写法。

平常我们只是剩去了default。

5.易错点

1.注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确

<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

2.注意 v-slot 只能添加在 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot attribute 不同。

3.v-slot的缩写是#,如#default  就是v-slot:default   #header就是v-slot:header。

4.默认插槽:我们平常在写v-slot=‘row’的时候其实v-slot:default=‘row’ 这两种都是默认插槽的写法,

我们平常只是省去了default。

不能坚持到底,即使是朽木也不能折断.只要坚持不停地用刀刻,就算是 金属玉石也可以雕出花饰.
雕刻一下便放弃,即使是腐朽的木头也不能被折断;雕刻并且持之以恒,就是金石也能被雕刻.
出自:荀子《劝学》。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值