1. 什么是插槽

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

可以把插槽

2. . 体验插槽的基础用法 (简写为#)

在封装组件时,可以通过 <solt>元素定义插槽,从而为用户预留内容占位符。示例代码如下

认为是组件封装期间,为用户预留的内容的占位符

<template>
	<p>这是MyCom1 组件的第一个p标签</p>
  //通过sort 标签,为用户预留内容占位符(插槽)
  <slot></slot>
  <p>这是MyCom1 组件最后一个P标签</p>
</template>
<my-com-1>
	// 在使用MyCom1组件是,为插槽指定具体的内容
  <p>用户自定义的内容</p>
</my-com-1>

2.1 没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何 插槽,则用户提供的任何自定义内容都会被丢弃。示例代码如下 :

<template>
	<p>这是MyCom1 组件的第一个p标签</p>
  //封装组件,没有预留任何插槽
  <p>这是MyCom1 组件的最后一个p标签</p>
</template>
<template>
	<p>这是MyCom1 组件的第一个p标签</p>
  //封装组件,没有预留任何插槽
  <p>这是MyCom1 组件的最后一个p标签</p>
</template>

在封装组件是,为预留的<slot>提供对应的值,这种用法,叫做"作用域插槽"(留有数据的插槽)

<template>
  <div class="app-container">
    <h1>App 根组件</h1>
    <hr />
    <Article>
      <template #title="{msg,user}">
        <h3>我是文章的标题</h3>
        <h4>{{msg}}</h4>
        <h4>{{user.name}}</h4>
      </template>
        <template #content>
        <p>我是文章的内容</p>
        <p>我是文章的内容</p>
        <p>我是文章的内容</p>
      </template>
      <template #footer>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p>
        <p>我是文章的页脚</p> 
      </template>
    </Article>
    <div class="box" style="display:none">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <Left>
        <!-- 默认情况下,在使用组件的时候提供的内容都会被填充到名字为default的插槽之中 -->
        <!-- 1.如果要内容填充到指定名称的插槽中,需要使用v-slot:这个指令 -->
        <!-- 2.v-slot:后面要跟上插槽的名字 -->
        <!-- 3.v-slot:指令不能直接用在元素身上,必须在template标签上 -->
        <!-- 4.teplate这个标签,他是一个虚拟的标签,只起到一个包裹的作用,但是不会被渲染为任何实质性的html元素 -->
        <!-- 5.v-slot:指令的简写形式是# -->
        <template #default>
          <p>这是在left组件的内容区域,声明的p标签</p>
        </template>
      </Left>
    </div>
  </div>
</template>

<script>
import Article from './components/Article.vue'
import Left from './components/Left.vue'
export default {
  components: { Left, Article },}
</script>

<style lang="less">
.app-container {
  padding: 1px 20px 20px;
  background-color: #efefef;
}
.box {
  display: flex;
}
</style>
<template>
  <div class="article-container">
    <!-- 文章的标题 -->
    <div class="header-box">
      <slot name="title" msg="Helo vue .js" :user="userinfo"></slot>
    </div>

    <!-- 文章的内容 -->
    <div class="content-box">
      <!-- 在封装组件是,为预留的<slot>提供对应的值,这种用法,叫做"作用域插槽"(留有数据的插槽) -->
      <slot name="content"></slot>
    </div>

    <!-- 文章的作者 -->
    <div class="footer-box">
      <slot name="footer"></slot>
    </div>

  </div>
</template>

<script>
export default {
  name: 'Article',

  data() {
    return {
      userinfo:{
        name:"张三",
        age:"23"
      }
    }
  },

  mounted() {},

  methods: {},
}
</script>

<style lang="less" scoped>
.article-container {
  >div{
    min-height: 150px;
  }
  .header-box {
    background-color: pink;
  }
  .content-box {
    background-color:lightblue;
  }
  .footer-box {
    background-color: lightcoral;
  }
}
</style>

 

 

 

 

 在设置是,要先确认接收方与发送方,接收方要通过template里面的v-slot来接收并且指定插槽名字,发送方需要在组件内定义数据通过slot来发送数据,发送形式可以有多种。

注意:1.默认情况下,在使用组件的时候提供的内容都会被被填充到名字为default的插槽之中

        2.如果要内容填充到指定的插槽中,需要v-slot:这个指令

        3.v-slot:后面要跟上插槽的名字(在name节点中定义的)

        4.v-slot:指令不能用在元素的身上,必须在template标签上或者在已经注册节点

        5.teplate这个标签的作用,但是不会被渲染为任何实质性的html元素

        6.v-slot:指令的简写形式是#

3.自定义指令

vue中的自定义指令分为两个类:

        3.1私有自定义指令

        在每个vue组件中,可以在directives节点(自定义指令节点)下声明私又自定义指令,实例代码如下
 

directives:{

   color:{
   //为绑定的html元素三设置红色的文字
       bind(el){
       el.style.color='red'
       }
   }

}

         el可以获取全局的dome元素,此外还可以有binding函数打印该函数可以发现里面存有value值,里面有获取到值

再此我们可以打印一下

directives: {
    color: {
      bind(el, binding) {
        el.style.color = 'red'
        console.log(binding)
      },
    },
},

 

 

        3.2全局自定义指令

在main.js文件中来增加全局自定义指令

// main.js 全局自定义指令
export default {
    diretive:{
        bind(el,binding){
            console.log('v-color的binding函数')
            el.style.color = binding.value
        },
        update(el,binding){
            console.log('v-color的binding函数')
            el.style.color = binding.value
        },
    
    }

}


// 或者可以简写成
Vue.diretive("color",function(el,binding){
    el.style.color = binding.value



})

此时该v-color全局可以调用,但是要注意的是需要在本组件里面定义好color数据,不然回出现undefind错误

完整代码如下

<template>
  <div class="app-containter">
    <h2>app根组件</h2>
    <hr />
    <Article>
      <template #title="{user,msg,use,data}">
        <button @click="color='red'">改变color的颜色值</button>
        <p v-color='color'>我是文章的标题</p>
      </template>
    </Article>
  </div>
</template>

<script>
import Article from './components/Article.vue'
import Left from './components/Left.vue'
import Right from './components/Right.vue'
export default {
  components: { Left, Right, Article },
  name: 'App',
  directives: {
    //定义名为color的指令,指向配置对象
    // color:{
    //   //当指令第一次被绑定到元素上的时候,会立即触发bind函数
    //   //形参中的el表示当前指令所绑定的DOM对象
    //   bind (el,binding) {
    //     console.log("v-color的binding函数")
    //     el.style.color = binding.value
    //     console.log(binding)
    //   },
    //   // 在dom更新的时候会触发updata里面的binding函数
    //   update (el,binding) {
    //     el.style.color = binding.value
    //     console.log("触发了updata的update函数")
    //   },
    // }
    //即包含了updata有包含了bind,因为两者的业务逻辑相似
    // color(el,binding){
    //   el.style.color=binding.value
    // }
    color: {
      bind(el, binding) {
        el.style.color = 'red'
        console.log(binding)
      },
    },
  },
  data() {
    return { comName: 'Left', color: 'blue' }
  },

  methods: {},
}
</script>

<style lang="less" scoped>
.app-containter {
  padding: 10px 10px;
}
</style>
<template>
  <div class="article-container">
    <p v-color='color'>article组件</p>
  </div>
</template>

<script>
export default {
  name: 'Article',
  components:{
  },
  
  data() {
    return {
        color:'red'
    };
  },
};
</script>

<style lang="less" scoped>
.article-container{
  .article-title{
    min-height: 150px;
    background-color: antiquewhite;
  }
  .article-content{
    min-height: 150px;
    background-color: orange;
  }
  .article-footer{
    min-height: 150px;
    background-color: pink;
  }
}
</style>

Logo

前往低代码交流专区

更多推荐