组件插槽和自定义属性

20 篇文章 1 订阅

组件插槽

用来实现组件内容的分发,通过slot标签,可以接收到写在组件标签内的内容

vue提供组件插槽的能力,允许开发者在封装组件时,把不确定的部分定义为插槽

基础使用–匿名插槽
  • 组件内使用slot 占位
  • 使用组件时 中间传入标签替换slot

Pannel.vue

<template>
  <div>
    <div class="title">
      <h4>鹅鹅鹅</h4>
      <span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
    </div>
    <div class="container" v-show="isShow">
      <!--1: 组件内使用slot 占位 -->
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
    }
  },
}
</script>

<style scoped>
h4 {
  text-align: center;
}
.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 10px;
}

.title h4 {
  line-height: 2;
  margin: 0;
}

.container {
  border: 1px solid #ccc;
  padding: 0 10px;
}
</style>

App.vue

<template>
  <div>
    <!-- 2 使用组件时 pannel 
    在组件中间 传入标签替换slot -->
    <pannel>
      <p>曲项向天歌</p>
      <p>曲项向天歌</p>
      <p>曲项向天歌</p>
      <p>曲项向天歌</p>
      <p>曲项向天歌</p>
    </pannel>
    <pannel>
      <img src="./assets/logo.png" alt="" />
    </pannel>
  </div>
</template>

<script>
import Pannel from './components/Pannel.vue'
export default {
  components: { Pannel },
}
</script>
默认内容

如果外面不给传,想给个默认显示内容

夹着内容默认显示内容,如果不给插槽slot传东西,就使用slot夹着的内容在原地显示

<slot>默认内容</slot>
具名插槽

当一个组件内有2处以上需要外部传入标签的地方

传入的标签可以分别派发给不同的slot位置

v-slot一般跟template标签使用(template是HTML5新出标签内容模板元素,不会渲染在页面上,一般被vue解析内部标签)

Pannel.vue

<template>
  <div>
    <div class="title">
      <slot name="title"></slot>
      <span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
    </div>
    <div class="container" v-show="isShow">
      <!--1: 组件内使用slot 占位 -->
      <slot name="content"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
    }
  },
}
</script>

App.vue

<template>
  <div>
    <!-- 2 使用组件时 pannel 
    在组件中间 传入标签替换slot -->
    <pannel>
      <template v-slot:title>
        <h4>鹅鹅鹅</h4>
      </template>
      <template v-slot:content>
        <span>我是内容</span>
      </template>
    </pannel>
       <!-- v-slot: 简写为 # -->
    <pannel>
      <template #title>
        <h2>hello</h2>
      </template>
      <template #content>
        <p>123</p>
      </template>
  </div>
</template>

总结:

v-slot: 可以简写为 #

slot的name属性起插槽名,使用组件时,template配合#插槽名传入具体的标签

作用域插槽

子组件里的值,在给插槽赋值时在父组件环境下使用

步骤:

  • 子组件:在slot上绑定属性和子组件内的值
  • 使用组件时,传入自定义标签,用template和v-slot=“自定义变量名scope”
  • scope变量名自动绑定slot上所有的属性和值

Pannel.vue

<template>
  <div>
    <div class="title">
      <!-- 1:slot上绑定属性和子组件内的值 -->
      <slot name="title" :msg="msg" tit="nihao"></slot>
      <span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
    </div>
    <div class="container" v-show="isShow">
      <!--1: 组件内使用slot 占位 -->
      <slot name="content"> </slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
      msg: 'hello world',
    }
  },
}
</script>

App.vue

<template>
  <div>
    <pannel>
      <!--2 传入自定义标签 template和v-slot:插槽名="自定义变量名" -->
      <template v-slot:title="scope">
        <!--3 scope上自动绑定slot上所有属性和值 -->
        <h4>{{ scope.tit }}</h4>
      </template>
      <template v-slot:content>
        <span>我是内容</span>
      </template>
    </pannel>
    <!-- v-slot: 简写为 # -->
    <pannel>
      <template #title>
        <h2>hello</h2>
      </template>
      <template #content>
        <p>123</p>
      </template>
    </pannel>
  </div>
</template>

总结:

组件内变量绑定到slot上,使用组件v-slot:插槽名=“自定义变量”,变量上会自动绑定属性和值

使用场景

需求:封装一个表格组件,在表格组件内循环产生单元格

  • 准备MyTable.vue组件—内置表格,传入数组循环铺设页面,把对象每个内容显示在单元格里
  • App.vue组件里,准备数据传入给MyTable.vue使用
  • 分析
    • 想要给td内显示图片,传入自定义的img标签(td中准备slot占位符,但是外面需要把图片地址赋予给src属性,在slot上把item数据进行绑定)

MyTable.vue

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>序号</th>
          <th>姓名</th>
          <th>年龄</th>
          <th>头像</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item, index) in list" :key="index">
          <td>{{ index + 1 }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
          <td>
            <slot :row="item">
              <!-- 默认值,使用组件不自定义标签显示默认文字 -->
              {{ item.headImgUrl }}
            </slot>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  props: ['list'],
}
</script>

App.vue

<template>
  <div>
    <my-table :list="list">
      <template v-slot="scope">
        <img :src="scope.row.headImgUrl" width="50" alt="" />
      </template>
    </my-table>
    <my-table :list="list">
      <template v-slot="{ row }">
        <a :href="row.headImgUrl">
          {{ row.headImgUrl }}
        </a>
      </template>
    </my-table>
  </div>
</template>

<script>
import MyTable from './components/MyTable.vue'
export default {
  components: { MyTable },
  data() {
    return {
      list: [
        {
          name: '张三',
          age: 18,
          headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
        },
        {
          name: '李四',
          age: 23,
          headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
        },
        {
          name: '王五',
          age: 45,
          headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
        },
      ],
    }
  },
}
</script>

自定义指令

除了核心功能默认内置的指令(v-model和v-show),vue允许我们注册自定义指令。 v-xxxx

html+css的复用的主要形式是组件

你需要对普通DOM元素进行底层操作,这时候就会用到自定义指令

目标:获取标签 扩展额外的功能

局部注册和使用

只能在当前组件中使用

局部指令
directives:{
‘指令名’:{
bind(el,binding,vnode){},
inserted(el,binding,vnode){}
}
}

在标签上使用自定义指令 v-指令名

inserted 指令所在标签 被插入到页面上触发(一次)
update 指令对应的数据/标签更新时 触发

<template>
  <div>
    <div class="main">
      <input type="text" v-focus />
    </div>
  </div>
</template>

<script>
/*
局部指令
directives:{
  '指令名':{
     bind(el,binding,vnode){},
     inserted(el,binding,vnode){}
  }
}

在标签上使用自定义指令  v-指令名

inserted 指令所在标签 被插入到页面上触发(一次)
update  指令对应的数据/标签更新时  触发
*/
export default {
  directives: {
    // 页面加载时获取焦点
    focus: {
      inserted(el, binding, vnode) {
        // console.log(el)
        el.focus()
      },
    },
  },  
}
</script>
全局注册和使用

在任何的.vue文件中使用

main.js中用Vue.directive 全局注册指令

// 全局注册
Vue.directive('gfocus', {
  inserted(el) {
    el.focus()
  },
})

自定义指令-传值

使用自定义指令,传入一个值

需求:定义color指令,传入一个颜色,给标签设置文字颜色

<template>
  <div>
    <div class="main">
      <input type="text" v-focus />
      <input type="text" v-gfocus />
    </div>
    <p v-color="theColor" @click="changeColor">修改文字颜色</p>
  </div>
</template>

<script>
/*
局部指令
directives:{
  '指令名':{
     bind(el,binding,vnode){},
     inserted(el,binding,vnode){}
  }
}

在标签上使用自定义指令  v-指令名

inserted 指令所在标签 被插入到页面上触发(一次)
update  指令对应的数据/标签更新时  触发
*/
export default {
  data() {
    return {
      theColor: 'blue',
    }
  },
  methods: {
    changeColor() {
      this.theColor = 'yellow'
    },
  },
  directives: {
    // 页面加载时获取焦点
    focus: {
      inserted(el, binding, vnode) {
        // console.log(el)
        el.focus()
      },
    },
    // 给标签设置文字颜色
    color: {
      inserted(el, binding) {
        el.style.color = binding.value
      },
      update(el, binding) {
        el.style.color = binding.value
      },
    },
  },
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值