当前位置: 首页 > article >正文

vue过渡,vue3组合式API详细介绍

7.过渡效果

vue提供了两个内置组件,可以帮助你制作基于状态变化的过渡和动画

  • Transition会在一个元素或组件进入和离开DOM时应用动画
  • TransitionGroup会在一个v-for列表中的元素或组件被插入,移动,或移除时应用动画
7-1过渡效果

在这里插入图片描述

过渡模式

<Transition mode="out-in">
  ...
</Transition>

组件间过渡

 <Transition name="yiLing">
            <slot></slot>
        </Transition>
7-2列表过渡

TransitionGroup是一个内置组件,用于对v-for列表中的元素或组件的插入,移除和顺序改变添加动画效果

区别

  • 默认情况下,他不会渲染一个容器元素,但是可以通过tag属性来指定一个元素作为容器元素来渲染

    在这里插入图片描述

  • 过渡模式在这里不可用,因为我们不再是在互斥的元素之间进行切换。

  • 列表中的每个元素必须有一个独一无二的key属性

  • css过渡的动画是会被应用在列表的元素上,而不是容器元素上

 <!-- <ul> -->
          <!-- 添加动画 
            tag="ul" 就相当于把TransitionGroup解析为ul标签了
        -->
          <TransitionGroup name="yiLing" tag="ul" mode="out-in">
            <li v-for="(data,index) in datalist" :key="data">
            {{ data }}
                <button @click="del(index)">删除</button>
        </li>
          </TransitionGroup>
        <!-- </ul> -->

移动动画(列表)

当某一项被插入或移除时,它周围的元素会立即发生“跳跃”而不是平稳地移动。我们可以通过添加一些额外的 CSS 规则来解决这个问题:

.list-move /* 对移动中的元素应用的过渡 */
{
  transition: all 0.5s ease;
}

/* 确保将离开的元素从布局流中删除
  以便能够正确地计算移动的动画。 */
.list-leave-active {
  position: absolute;
}
7-3 可复用过渡

得益于 Vue 的组件系统,过渡效果是可以被封装复用的。要创建一个可被复用的过渡,我们需要为 Transition 组件创建一个包装组件,并向内传入插槽内容:

app.vue

<template>
    <div>
        <button @click="isShow=!isShow">显示/隐藏</button>
        <kerwinTransition myname="rtol">
          <div v-if="isShow">11111111111111</div>
        </kerwinTransition>
    </div>
</template>
<script>
import kerwinTransition from './kerwinTransition.vue'
export default {
    components: {
        kerwinTransition
    },
    data() {
        return {
            isShow: true,
           
        }
    },
}
</script>

kerwinTransition.vue

<template>
    <div>
       <Transition :name="myname">
         <slot></slot>
       </Transition>
    </div>
</template>
<script>
export default {
    props:["myname"]
}
</script>
<style>
    /* 下面我们会解释这些 class 是做什么的 */
.ltor-enter-active{
    animation: animate 0.5s;
}
.ltor-leave-active {
    animation: animate 0.5s reverse;
}

@keyframes animate {
    0%{
        transform: translateX(100px);
        opacity: 0;
    }
    100%{
        transform: translateX(0px);
        opacity: 1;
    }
}
.rtol-enter-active{
    animation: animate 0.5s;
}
.rtol-leave-active {
    animation: animate 0.5s reverse;
}

@keyframes animate {
    0%{
        transform: translateX(-100px);
        opacity: 0;
    }
    100%{
        transform: translateX(0px);
        opacity: 1;
    }
}
html,body{
    overflow-x: hidden;
}
</style>

animate.css库的使用

官网地址:https://animate.style/

案例

<template>
    <div>
        <button @click="isShow=!isShow">切换</button>
        <!-- 使用过渡组件,里面只能写一个元素的插入和删除 -->
        <!-- 这里的name要和css的name一致 -->
        <!-- enter-active-class:使用的是animate.css库的动画 -->
        <!-- <transition name="yiLing" enter-active-class="animate__animated animate__bounceInRight" leave-active-class="animate__animated animate__bounceOutRight">
            <div v-show="isShow">123</div>
        </transition> -->
        <!-- 使用动画 -->
        <transition name="yiLing">
            <div v-show="isShow">123</div>
        </transition>
    </div>
</template>
<script>
//----------------引入animate库-----------------
import "animate.css";
export default {
    data() {
        return {
            isShow:true
        }
    },
}
</script>
<style>
/* 过渡 */
/* .yiLing-enter-active,
.yiLing-leave-active {
  transition: opacity 0.5s ease;
}

.yiLing-enter-from,
.yiLing-leave-to {
  opacity: 0;
} */
/* 动画 */
.yiLing-enter-active {
  animation: bounce-in 0.5s;
}
.yiLing-leave-active {
  animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: translateX(100px);
    opacity: 0;
  }
 
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}
</style>

四.vue3组合式API

起初定义的是Vue-Function-API,后经过社区意见收集,更名为Vue-Composition-API.

在这里插入图片描述

1.reactive

作用:包装响应式对象,非包装对象,可以认为是模版中的状态
  • template可以放兄弟节点
  • reactive类似于useState,如果参数是字符串,数字,布尔,null,undefined等基本数据类型,会报警告,value cannot be made reactive, 所以应该设置对象,这样可以数据驱动页面
<template>
    <div>
        {{ obj.myName }}
        <button @click="handleClick">click</button>
    </div>
</template>
<script>
import { reactive } from "vue"
export default {
    // 页面一加载,setup就会自动执行
    setup() {
        console.log("setup:复合api,状态,函数,计算属性,生命周期....");
        // reactive:支持复杂数据类型
        const obj = reactive({
                myName: "张三",
        })
        const handleClick = () => {
            // 修改状态
            obj.myName="123"
            console.log(obj.myName);
        }
        return {
            obj,
            handleClick
        }
        }
    }
</script>

2.ref

作用:创建一个包装式对象,含有一个响应式属性value,它和reactive的差别,就是前者没有包装属性value,还有就是前者不能定义基本的数据类型

<template>
    <div>
        {{ myName }}
        <button @click="handleClick">click</button>
    </div>
</template>
<script>
import { ref } from "vue"
export default {
    setup(props) {
        console.log("setup:复合api,状态,函数,计算属性,生命周期");
        const myName = ref("小小易")//字符串,数字,bool,对象,数组,比reactive更为强大
        const handleClick = () => {
            // ref,使用value包裹值,所以使用的使用需要.value
            console.log(myName);
            myName.value="123"
        }
        return {
            myName,
            handleClick
        }
    }
}
</script>
2-1ref嵌套在reactive中
<template>
    <div>
        {{ val }}
        <input type="text" v-model="obj.val" @keyup.enter="add">
        <ul>

            <li v-for="(data,index) in obj.dataList " :key="data">
                {{ data }}
                <button @click="del(index)">del</button>

            </li>
        </ul>
    </div>
</template>
<script>
import { reactive, ref } from "vue"
export default {
    setup(props) {
            // 定义ref的val;
        const val = ref("")
        const obj = reactive({
            // 把ref的val赋值给obj的val,放在reactive里面
            val,
            dataList:[]
        })
        const add = () => {
            console.log(obj);
            // 使用ref获取值的方式
            if( val.value.trim() != "") {
                // 记得有一层value包裹
                // 使用reactive添加值的方式
                obj.dataList.push(val.value)
                console.log(val);
               val.value=""
            }
        }
        const del = (index) => {
            obj.dataList.splice(index,1)
        }
        return {
          obj,
            add,
            del,
            val
            }
        }
    }
</script>
2-2ref绑定节点
<template>
    <div>
        <div ref="myDom">123</div>
        <button @click="dom">获取节点</button>
    </div>
</template>
<script>
import { ref } from "vue"
export default {
        setup(props) {
        console.log(props);
        // 获取节点,给初始值为null
        const myDom = ref(null);
        const dom = () => {
             // 获取节点
                console.log(myDom.value);
        }
        return {
            dom,
            myDom
        }
    }
        
    }
</script>
2-3toRefs
默认直接展开State,那么此时reactive数据变成普通数据,通过toRefs,可以把reactive里的每个属性,转换为ref对象,这样展开后,就会变成多个ref对象,依然具有响应式特性
目的:目的是为了在传递属性时保留响应性
<template>
    <div>
        <input type="text" v-model="val" @keyup.enter="add">
        <ul>
            <li v-for="(data,index) in dataList" :key="data">
                {{ data }}
                <button @click="del(index)">del</button>
            </li>
        </ul>
    </div>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
        setup(props) {
        const obj = reactive({
            val: "",
            dataList: []
                
        })
        // 对象解构以后,就可以把reactive定义的使用ref的方式进行使用
        const {val,dataList}=toRefs(obj)
        const add = () => {
            console.log(val.value);
            if (val.value.trim!="") {
                obj.dataList.push(obj.val)
                obj.val = ""
            }
        }
        const del = (index) => { 
            obj.dataList.splice(index,1)
        }
        return {
            ...toRefs(obj),//reactive==>n个ref单独管理
            del,add
            }
    }
        
    }
</script>

3.计算属性

computed是一个回调函数

模糊搜索案例

<template>
    <div>
        <input type="text" v-model="search">
        <ul>
            <li v-for="data in computedList" :key="data">
                {{ data }}
            </li>
        </ul>
    </div>
</template>
<script>
// 引入计算属性和ref
import { computed, ref } from "vue"
export default {
    setup(props) {
        const search = ref("");
        const datalist = ref(["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"])
        // computed是一个回调函数
        const computedList = computed(() => {
           return datalist.value.filter(item=>item.includes(search.value))
        })
        return {
            search,
            datalist,
            computedList
        }
    }
   }
</script>ba

对上述代码进行优化

创建一个hooks文件夹

在此下面创建一个useFilter.js文件

import { computed, ref } from "vue"
function useFilter(datalist) {
    const search = ref("");
const computedList = computed(() => {
    return datalist.value.filter(item => item.includes(search.value))
    
})
return {
    search,
    computedList
}
}
export default (useFilter);

App.vue

<template>
    <div>
        <input type="text" v-model="search">
        <ul>
            <li v-for="data in computedList" :key="data">
                {{ data }}
            </li>
        </ul>
    </div>
</template>
<script>
import useFilter from "./hooks/useFilter";
import { ref } from "vue"
export default {
    setup(props) {
      
        const datalist = ref(["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"])
      
        return {
          ...useFilter(datalist),
          datalist
        }
    }
   }
</script>

4.watch

计算属性允许我们声明性计算衍生值,然而在有些情况下,我们需要状态在状态变化时执行一些"副作用":列如更改DOM,或是根据异步操作的结果去修改另一处的状态。

在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数:

第一个参数是监听的值,第二个参数可以执行监听时候的回调

<template>
    <div>
        <input type="text" v-model="myText">
        <input type="text" v-model="myage">
    </div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
    setup(props) {
        const myText = ref('')
        const myage = ref('')
        const obj = reactive({
            myText
        })
        //----------------第一种ref-----------------
        // watch(myText, (newValue, oldValue) => {
        //     // 异步
        //     console.log("异步",newValue,oldValue,myText);
        // }, { immediate: true, deep: true })
        //----------------第二种ref-----------------
        // watch(() => {return myText.value }, (newValue, oldValue) => {
        //     console.log("异步",newValue,oldValue,myText);
        // })
          //----------------第三种多个ref-----------------
        // watch([myText,myage], (newValue, oldValue) => {
        //     console.log("异步",newValue,oldValue,myText,myage);
        // })
        //----------------第一种reactive-----------------
        // watch(() => obj.myText, (newValue, oldValue) => {
        //     console.log("异步",newValue,oldValue,myText);
        // })
         //----------------第二种reactive-----------------
         watch(obj, (newValue, oldValue) => {
            console.log("异步",newValue,oldValue,obj.myText);
        })
        return {
            myText,
            myage,
            obj
        }
    }
}
</script>

5. VCA中的watchEffect函数

(1)watch:

  • 具有一定的惰性lazy 第一次页面展示的时候不会执行,只有数据变化的时候才会执行(可以添加immediate:true),则页面一加载就可以箭头数据的变化

          watch(myText, (newValue, oldValue) => {
                // 异步
                console.log("异步",newValue,oldValue,myText);
            }, { immediate: true, deep: true })
    
  • 参数可以拿到当前值和原始值

  • 可以侦听多个数据的变化,用一个侦听器承载

(2)watchEffect:

  • 立即执行,没有惰性,页面的首次加载就会执行。
  • 自动检测内部代码,代码中有依赖 便会执行
  • 不需要传递要侦听的内容 会自动感知代码依赖,不需要传递很多参数,只要传递一个回调函数
  • 不能获取之前数据的值 只能获取当前值
  • 一些异步的操作放在这里会更加合适
<template>
    <div>
        <input type="text" v-model="myText">
        <input type="text" v-model="myAge">
        <input type="text" v-model="obj.myText">
    </div>
</template>
<script>
import { watchEffect, ref,reactive } from "vue"
export default {
    setup(props) {
        const myText = ref("")
        const myAge = ref("")
        const obj = reactive({
            myText:""
        })
        //----------------ref-----------------
        watchEffect(()=>{
            console.log(`基于mytext和myage条件改变,发ajax`,myText.value,myAge.value)
        })
        //----------------reactive-----------------
        watchEffect(()=>{
            console.log(`基于mytext和myage条件改变,发ajax`,obj.myText)
        })
        return {
            myAge,
            myText,obj
        }
    }
}
</script>

6. prop & emit

App.vue

<template>
    <div>
        <!-- @event="handleEvent":处理子组件传过来的数据 -->
        <!-- title="首页":给子组件传值 -->
        <Child title="首页" @event="handleEvent" :isLeftShow="false"></Child>
    </div>
</template>
<script>
    import Child from "./components/Child.vue";
export default {
    components: {
        Child
    },
        setup(props) {
            const handleEvent = (el) => {
                // el:获取子组件传过来的数据
                console.log("父组件定义",el);
            }
            return {
                handleEvent
            }
    }
        
    }
</script>

Child.vue

<template>
    <div>
        {{ title }}
        <button @click="handleClick">子传父</button>
    </div>
</template>
<script>
export default {
    props: {
        title: {
            // 限定类型
            type: String,
        },
        isLeftShow: {
            type:Boolean
        }
    },
    // {title },{emit}接收父传过来的数据
    setup({title },{emit}) {
        const handleClick = (el) => {
          emit("event","1111")
        }
        return {
            handleClick
        }
    }
}
</script>

7. VCA中provide&inject

provide、inject 是 vue-composition-api 的一个功能:依赖注入功能

App.vue

<template>
    <div>
        <Tabber></Tabber>
        <Navbar></Navbar>
    </div>
</template>
<script>
    import Navbar from './Navbar.vue'
import Tabber from './Tabber.vue'
import {  provide,ref } from 'vue';
export default {
    components: {
        Navbar,
        Tabber
    },
    setup(props) {
            const title=ref('首页')
            provide("myTitle",title)
        }
    }
</script>

Navbar

<template>
    <div style="text-align: center;">
       {{ title }}
    </div>
</template>
<script>
import { inject } from 'vue'
export default {
    setup(props) {
        //进行注入
        const title = inject("myTitle")
        return {
            title
        }
    }
        
    }
</script>

Tabber

<template>
    <div>
       <ul>
            <li v-for="data in dataList" :key="data" @click="handleClick(data.name)">//(data.name)传值
                {{ data.name }}
            </li>
           
       </ul>
    </div>
</template>
<script>
import { ref, inject } from 'vue'

export default {
    setup(props) {
        //进行注入
        const title=inject("myTitle")
            const dataList = ref([{
            name: "首页"
        },
        {
            name: "列表"
        },
        {
            name: "我的"
        }
        ])
        const handleClick = (data) => {
            console.log(title.value);
            //改变值
            title.value=data
        }
        return {
            dataList,
            handleClick
            }
        }
    }
</script>
<style>
ul{
    list-style: none;
    display: flex;
    position: fixed;
    bottom: 0;
    width: 100%;
  
}
li{
    flex: 1;
    text-align: center;
        height: 60px;
        line-height: 60px;
}
</style>

8. VCA中的生命周期

在这里插入图片描述


http://www.kler.cn/news/135461.html

相关文章:

  • Ajax之引入
  • 配置 `PostgreSQL` 与 `Keepalived` 以实现高可用性
  • 开发者生态:共享知识,携手共进,共创技术辉煌
  • PHP项目学习笔记-萤火商城-增加一个模块(表涉及到的操作和文件)
  • vue3项目安装eslint和prettier
  • mysql面试题——存储引擎相关
  • Typora下载安装 (Mac和Windows)图文详解
  • Python利器:os与chardet读取多编码文件
  • 德语B级SampleAcademy
  • Golang环境搭建Win10(简洁版)
  • Redux-状态管理组件
  • 053-第三代软件开发-元对象系统
  • Java中异常的概念、体系结构和分类
  • docker安装elasticsearch,elasticsearch-head
  • 【数字图像处理】Gamma 变换
  • 【Electron】electron-builder打包失败问题记录
  • svn问题集
  • 解决requests 2.28.x版本SSL错误:证书验证失败
  • 【Linux】Linux下的基础IO
  • Redis字典实现
  • Pikachu漏洞练习平台之XXE(XML外部实体注入)
  • C语言——写一个函数,每调用一次这个函数,就会将num的值增加1
  • Java拼图小游戏
  • 数电实验-----实现74LS153芯片扩展为8选1数据选择器以及应用(Quartus II )
  • vue3+ts扩展全局属性
  • Python编程陷阱(九)
  • Java 算法篇-链表的经典算法:判断回文链表、判断环链表与寻找环入口节点(“龟兔赛跑“算法实现)
  • 【信息安全】浅谈SQL注入攻击的概念、原理和防范措施:简单分析六种常见攻击方式
  • ubuntu下载conda
  • 基于RK3588全高端智能终端机器人主板