slot插槽、transition动画、filter过滤器

本文深入探讨Vue组件的高级特性,包括slot插槽的使用,尤其是具名插槽的应用;详细阐述vue中的动画实现方式,如CSS过渡、JavaScript操作DOM以及结合第三方库;并介绍了动态组件与keep-alive的配合使用,以及在Vue2.x中如何创建自定义过滤器filter。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

slot 插槽

  • 作用: 可以让我们在组件中书写内容
<div id="app">
    <Hello>
      <header>  头部  </header>
      <section> 内容 </section>
      <footer> 底部 </footer>
    </Hello>
</div>

<template id="hello">
    <div>
      hello
      <slot></slot>
    </div>
</template>
Vue.component( 'Hello', {
    template: '#hello'
  })

  new Vue({
    el: '#app'
  })

- 具名插槽

<div id="app">
    <Hello>
      <header slot = "header">  头部  </header>
      <section slot = "content"> 内容 </section>
      <footer slot = "footer"> 底部 </footer>
    </Hello>
</div>

  <template id="hello">
    <div>
      <slot name = "header"></slot>
      <slot name = "content"></slot>
      hello
      <slot name = "footer"></slot>
    </div>
  </template>

动画

vue中实现过渡或是动画一共提供了这样四种形式:

  1. 在 CSS 过渡和动画中自动应用 class — 自己写css3动画

  2. 可以配合使用第三方 CSS 动画库,如 Animate.css – 别人写好了类名,我们用

  3. 在过渡钩子函数中使用 JavaScript 直接操作 DOM – 自己用原生js来写动画

  4. 可以配合使用第三方 JavaScript 动画库,如 Velocity.js – 用别人写好的动画库

    1. vue只要一使用transition组件就会自动添加6个类名 和 8 个钩子函数
    1. transition组件如果有name选项,就可以将类名 v- 换成 ‘name’- 类名
    1. 使用第三方的css过渡库 animate.css

一、

<div id="app">
    <button @click = 'flag = !flag'> 切换 </button>
    <transition name="fade" mode="">
      <p v-show = 'flag'> 切换的内容 </p>
    </transition>
  </div>
<style>
    /* 6个类名  v-enter  v-leave-to  v-enter-active  v-leave-active*/
    .fade-enter-active, .fade-leave-active{
      transition: all 1s; 
    }
    .fade-enter, .fade-leave-to{
      opacity: 0;
    }
</style>
new Vue({
    el: '#app',
    data: {
      flag: true
    }
  })

二、

<div id="app">
    <button @click = 'flag = !flag'> 切换 </button>
    <transition 
      name="fade" mode="out-in"
      enter-active-class = "animated slideInLeft"
      leave-active-class = "animated slideOutLeft"
    >
      <p v-show = 'flag'> 切换的内容 </p>
    </transition>
    <transition 
      name="fade" mode="in-out"
      enter-active-class = "animated slideInLeft"
      leave-active-class = "animated slideOutLeft"
    >
      <p v-show = '!flag'> 切换的内容 </p>
    </transition>
</div>

动态组件:

  1. 动态组件是vue内部提供了一个叫做component的组件,这个组件身上可以通过绑定is属性来进行组件的切换
  2. keep-alive组件可以进行组件的内容缓存,将组件的内容存入浏览器缓存中,这样可以大大的节省街切换的事件

keep-alive 和 component动态组件两者常常一起搭配使用

动态组件:

<div id="app">
      <button @click = " name = name === 'Aa'?'Bb':'Aa'"> 切换 </button>
      <component :is = "name"></component>
  </div>

动态组件-缓存:

<div id="app">
      <button @click = " name = name === 'Aa'?'Bb':'Aa'"> 切换 </button>
      <keep-alive include="">
        <component :is = "name"></component>
      </keep-alive>
  </div>
Vue.component( 'Aa',{
    template: '<h3> AA </h3>'
  })
  Vue.component( 'Bb',{
    template: '<h3> BB </h3>'
  })
  new Vue({
    el: '#app',
    data: {
      name: 'Aa'
    }
  })

filter自定义过滤器

**过滤器: **
vue 1.x内部提供提供了 10 个过滤器, 这10个过滤器是针对 数字 纸币符号 日期 大小写 小数位数等的格式化。vue2.x取消了内置的过滤器,同时vue 对数据提供一个 filter 的处理器来设置自定义的过滤器

  什么叫过滤器?
    格式化数据的一个工具
    举例:  12.22225   ---> 12.2 
        Tue May 28 2019 10:15:08 GMT+0800 (China Standard Time)  -- >   2019/05/28

  过滤器一样也有两种声明形式
    全局声明
      Vue.filter(过滤器名称,回调函数)  回调函数中有一个参数value
      value值就表示的是格式化数据的值
    局部声明
      new Vue({
        filters: {
          '过滤器名称': function( value ){
            return
          }
        }
      })

    过滤器的回调函数必须有返回值

    如何使用使用过滤器?
      我们用一个叫做管道符的来使用过滤器

      举例: 
          数据 | 过滤器名称
<div id="app">
    <p> {{ time | date('*') }} </p>
</div>
// 全局声明

  Vue.filter( 'date', function ( val,type ) {
    var date = new Date( val )
    return `¥${ date.getFullYear()} ${ type } ${ date.getMonth() + 1 } ${ type } ${ date.getDate() }`
  })

  new Vue({
    el: '#app',
    data: {
      time: Date.now()
    }
  })
<template> <myModal :params="{title: $t('选择报警类型')}" :modalWidthSize="'middle'" :visible="visible" @submit="handleOk" @cancel="handleCancel"> <template v-slot:header><span></span></template> <template v-slot:body> <div class="alarm_type_modal"> <div class="main_content" v-if="alarmTypeList.length"> <div class="search_item"> <a-input-search @search="handleAlarmTypeSearch" :placeholder="$t('请输入报警类型名称')" /> </div> <template v-if="isShowList"> <div class="check_item"> <div class="all_check"> <a-checkbox :indeterminate="indeterminate" :checked="checkAll" @change="onCheckAllChange"> {{ $t("用电告警")}} </a-checkbox> <img class="down" @click="changeIcon" :class="{'up': expanded}" src="~@/assets/img/down.png" /> </div> <div :class="['check_group_list', expanded ? 'checkboxUp': 'checkboxDown' ]"> <a-checkbox-group v-model="checkedList" @change="onCheckChange"> <template v-for="el in filteredList"> <a-checkbox :key="el.alarmTypeCode" :value="el.alarmTypeCode"> <span :title="$t(el.alarmTypeName)"> {{ $t(el.alarmTypeName) }} </span> </a-checkbox> </template> </a-checkbox-group> </div> </div> </template> <noData v-else /> </div> <a-space :size="64" v-else> <a-spin tip="加载中,请稍候..." /> </a-space> </div> </template> </myModal> </template> <script> import factory from '../../factory'; import noData from '@/components/tableNoData' import myModal from "@/components/scfComponents/modalComponents/modal.vue"; export default { components: { noData, myModal }, data() { return { visible: false, isShowList: true, indeterminate: false, checkAll: false, expanded: true, checkedList: [], // 所有选中项 alarmTypeList: [], // 原始数据 filteredList: [], // 过滤后列表 // checkedListBak: [] } }, props: { alarmTypeArr: { type: Array, default: [] } }, computed: { alarmTypeCodes() { return this.filteredList.map(item => item.alarmTypeCode) }, // 当前可见项的选中状态 alarmTypeChecked() { return this.checkedList.filter(code => this.alarmTypeCodes.includes(code)); }, }, watch: { // 监听过滤后的列表变化 filteredList: { handler(newVal) { this.isShowList = newVal.length > 0; }, immediate: true } }, methods: { getAlarmTypeList() { factory.getAlarmTypeList().then(res => { this.alarmTypeList = res || [] this.filteredList = [...this.alarmTypeList]; // 初始化过滤列表 this.updateCheckState(); }) }, // 打开弹窗 showModal(data) { this.visible = true this.checkedList = [...data]; this.getAlarmTypeList(); }, // 报警类型搜索 handleAlarmTypeSearch(val) { const searchTerm = val.toLowerCase().trim(); if (!searchTerm) { this.filteredList = [...this.alarmTypeList]; } else { this.filteredList = this.alarmTypeList.filter(item => item.alarmTypeName.toLowerCase().includes(searchTerm) ); } this.updateCheckState() }, // 更新选择状态 updateCheckState() { this.checkAll = this.alarmTypeChecked.length === this.alarmTypeCodes.length; this.indeterminate = !!this.alarmTypeChecked.length && !this.checkAll; }, // 全选 onCheckAllChange(e) { Object.assign(this, { checkedList: e.target.checked ? [...this.alarmTypeCodes] : [], indeterminate: false, checkAll: e.target.checked, }); }, changeIcon() { this.expanded = !this.expanded }, // 单选 onCheckChange() { this.updateCheckState() }, // 确定 handleOk() { this.visible = false }, // 取消 handleCancel() { this.visible = false } }, } </script> <style lang="less" scoped> .alarm_type_modal { width: 100%; display: flex; padding: 24px; box-sizing: border-box; justify-content: center; .main_content { width: 100%; min-height: 400px; position: relative; border-radius: 8px; border: solid 1px #c5cdd6; padding: 23px 10px 10px 16px; .search_item { width: 100%; margin-bottom: 15px; } .check_item { border-radius: 4px; margin-bottom: 10px; border: 1px solid var(--split); .all_check { display: flex; padding: 10px 16px; align-items: center; justify-content: space-between; background-color: #f0f3f7; .down { width: 13px; height: 8px; transition: all 0.5s; cursor: pointer; } .up { transform: rotate(180deg); } } .check_group_list { width: 100%; overflow: hidden; transition: all 1s; .ant-checkbox-group { width: 100%; padding: 8px 0 8px 14px; .ant-checkbox-wrapper { margin: 0; width: 25%; padding: 4px; overflow: hidden; line-height: 28px; padding-left: 18px; white-space: nowrap; text-overflow: ellipsis; border-right: 1px solid #f0f3f7; &:nth-child(4n) { border-right: none; } } } } .checkboxDown { height: 0px; } .checkboxUp { min-height: 30px; } } } } </style> 代码评审
最新发布
08-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值