Vue3.x学习笔记(进阶)

进阶

全局组件

  • <script src=“https://cdn.bootcdn.net/ajax/libs/vue/3.1.2/vue.global.js”>
  • 国内地址
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--    <script src="https://unpkg.com/vue@next"></script>-->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.2/vue.global.js"></script>

</head>
<body>
<div id="app"></div>
</body>
<script>

    const app = Vue.createApp({
    //组件复用及调用
        template: `
      <website/>
      <describe/>
      <count/>
      <count/>
      <count/>
        `,
    });
        //全局组件定义
    app.component('website', {
        template: `<h2>liuyifei</h2>
`
    }) ,
        app.component('describe', {
            template: `  <h2>刘亦菲</h2>
`
        }),
        app.component('count',{
            data(){
                return{
                    count:0
                }
            },
            template:`
           <div>{{count}}</div>
           <button @click="count++">count</button>
            `
        })
    const vm = app.mount("#app");
</script>
</html>

局部组件

  • 在 const app = Vue.createApp({})外层定义
const counter = {
        data() {
            return {
                count: 0
            }
        },
        template: `
          <div>{{ count }}</div>
          <button @click="count++">count</button>
        `
    }
  • 注册
    const app = Vue.createApp({
        components: {
            //常用简写方法
            //counter
            web: counter
        },
           })
  • 调用
      template: `
              <website/>
              <describe/>
              <web/>
            `,

父子组件的静态传值

  • 父组件
    const app = Vue.createApp({
             template: `
           <h2>liuyifei</h2>
           <son name="刘亦菲"/>
            `,
    });

  • 子组件
    app.component('Son', {
    //接收参数为数组
        props:['name'],
        template: `
    <div>{{name}}</div>
    `
    })

父子组件的动态传值

  • 父组件
    const app = Vue.createApp({
        data(){
            return{
          name:'刘小菲'
            }
        },

        template: `
           <h2>liuyifei</h2>
           <son :name="name"/>
            `,
    });
  • 子组件
    app.component('Son', {
    //接收参数为数组
        props:['name'],
        template: `
    <div>{{name}}</div>
    `
    })

动态绑定函数

  • 父组件
    const app = Vue.createApp({
        data() {
            return {
                name: '刘小菲',
                pay: () => {
                    alert("收到钱")
                }
            }
        },
        /*此时的<pay/>调用了子组件
        * :pay="pay"绑定了参数,两边一致*/
        template: `
          <h2>liuyifei</h2>
          <son :name="name"/>
          <pay :pay="pay"/>
        `,
    });

  • 子组件
       app.component("pay", {
        /*传递参数*/
        props: ['pay'],
        methods: {
            handleClick() {
                alert("给你钱")
                //调用pay()方法
                this.pay()
            }
        },
        template: `
          <div @click="handleClick">马前卒</div>
        `
    })

组件传值时的校验操作

    app.component('Son', {
        props:
            {
                name:{
                    //限制类型
                    type:String,
                    //精准判断
                     validator(value) {
                        //没有则传递-1
                        return value.search("菲")!=-1
                    },
                    //限制必须有值
                    // required:true,
                    //默认值
                    default:"刘亦菲"
                }
            },
        template: `
          <div>{{ name }}</div>
        `
    })

单项数据流机制

  • 父组件,此时counter定义在父组件中
    const app = Vue.createApp({
        data() {
            return {
                counter:0
            }
        },

        template: `
          <h2>刘亦菲</h2>
          <counter :counter="counter"/>
          <counter :counter="counter"/>
          <counter :counter="counter"/>
               `,
    });
  • 子组件
app.component(`counter`,{
props:[`counter`],
    template:`
    <div>{{ counter }}</div>
    <button  @click="counter++"> 按钮</button>
    `
})
  • 数据从父级组件传递给子组件,只能单向绑定。子组件内部不能直接修改从父组件传递过来的数据。
  • 控制台告警readonly
vue.global.js:1290 [Vue warn]: Attempting to mutate prop "counter". Props are readonly. 
  • 修改子组件
  • 使用newCounter接收this.counter,而不对父组件中的counter进行修改
app.component(`counter`,{
props:[`counter`],
    data(){
    //使用newCounter接收this.counter,而不对父组件中的counter进行修改
    return{
        newCounter:this.counter
    }
    },
    template:`
    <div>{{ newCounter }}</div>
    <button  @click="newCounter++"> 按钮</button>
    `
})

Non-props使用技巧

  • 父组件
    const app = Vue.createApp({
        template: `
          <h2>刘亦菲</h2>
          <hello style="color: #42b983" msg="liuyifei" />
       `,
    });

  • 子组件
    app.component("hello", {
        //使用props:接收样式后,样式无效
        // props:['style'],
        // inheritAttrs默认为true,单独设置为false时Non-props不生效,设置为true时, Non-props生效
        // inheritAttrs:false,
        // v-bind:msg="$attrs.msg"单独接收父组件中的msg元素
        // v-bind="$attrs"接收父组件中的全部元素
        template: `
       <h3 v-bind:msg="$attrs.msg">hello world</h3>
       <h3>hello world</h3>
       <h3>hello world</h3>
        `
    })

子组件调用父组件方法/传值/校验

  • 父组件
    const app = Vue.createApp({
        data() {
            return {
                counter:0
            }
        },
methods:{
  handleAddCounter(param){
      console.log(param)
      //业务逻辑在子组件
      this.counter=param
  }
},
//此时共享了父组件的中的counter
        template: `
          <h2>刘亦菲</h2>
          <counter :counter="counter" @add="handleAddCounter"/>
          <counter :counter="counter" @add="handleAddCounter"/>
          <counter :counter="counter" @add="handleAddCounter"/>
                  `,
    });

  • 子组件
       app.component(`counter`,{
        props:[`counter`],
        //对子组件调用父组件时,调用前需要声明
        // emits:['add'],
        //注意:校验和业务逻辑须同时在子组件
        emits: {
            add: (value) => {
                return value < 20 ? true : false
            }
        },
        methods:{
          handleClick() {
              this.$emit('add',this.counter+3)
          }
        },
        template:`
    <div>{{ counter }}</div>
    <button  @click="handleClick"> 按钮</button>
    `
    })
  • 逻辑
  • <button @click=“handleClick”> 按钮</button>调用子组件的handleClick()方法
  • this.$emit(‘add’,2)调用父组件 <counter :counter=“counter” @add=“handleAddCounter”/>中 @add=“handleAddCounter”
  • @add="handleAddCounter"中handleAddCounter()是父组件中的方法
  • 注意:校验和业务逻辑须同时在子组件

slot

  • 父组件
    const app = Vue.createApp({
        data() {
            return {
                girlfriend: `刘亦菲`
            }
        },
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
        <girlfriend>马儿扎哈</girlfriend>
        <girlfriend style="color: #42b983">{{ girlfriend }}</girlfriend>
        <girlfriend style="color: #42b983">
        <project/>
        </girlfriend>
 `
    })
  • 子组件
  app.component('girlfriend', {
        data() {
            return {
                girlfriend: `古力娜扎`
            }
        },
        template: `
    <div>
    <span>经过你的慎重考虑.最终选择了。</span>
    <span>
         <slot></slot>
    </span>
</div>
    `
    })
    
      app.component('project', {
        template: `
        <span style='color:blue;'>花生米</span>
        `
    })

  • 插入的位置在 <slot></slot>之间
 <span>
         <slot></slot>
    </span>

在这里插入图片描述

  • 父模板里调用的数据属性,使用的都是父模板里的数据
  • 子模板里调用的数据属性,使用的都是子模板里的数据
  • 因此,<girlfriend style=“color: #42b983”>{{ girlfriend }}在父模板中调用,所以显示刘亦菲

插槽默认值

  • 父模板
    const app = Vue.createApp({
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
                    <girlfriend>
                    </girlfriend>
                  `
    })

  • 子模版
  • <girlfriend></girlfriend>中间没有值时,默认为子模板中的值
    app.component("girlfriend", {
        template: `
    <div>
    你选择了<slot>新垣结衣</slot>
    </div>
    `
    })

具名插槽

  • 父模板
  • 调用方法:子模板标签 <pron>中接<template v-slot:one>,其中one为具名
    const app = Vue.createApp({
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
                    <pron>
                    <template v-slot:one><div>1.Chet选择了</div></template>
                    <template v-slot:two><div>3.598</div></template>
                    </pron>
`
    })
  • 子模版
    app.component("pron",{
        template:`
        <div>
        <slot name="one"></slot>
                <div>2.马儿扎哈</div>
        <slot name="two"></slot>
</div>
        `
    })

具名插槽简写

  • 父模板
  • 调用方法:子模板标签 <pron>中接<template #one>,其中one为具名
    const app = Vue.createApp({
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
                    <pron>
                    <template #one><div>1.Chet选择了</div></template>
                    <template #two><div>3.598套餐</div></template>
                    </pron>
`
    })

插槽作用域

  • 父模板
  • v-slot="props"接收来自子模板的 :item="item"参数props(任意取名)是{ “item”: “刘亦菲” },输出时使用{{props.item}}
    const app = Vue.createApp({
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
                   <list v-slot="props">
        <div>{{props.item}}</div>
    </list>
`
    })
  • 子模版
  • <slot v-for=“item in list” :item=“item” />中 v-for="item in list"遍历数据,:item="item"传递参数
    app.component("list", {
        data() {
            return {
                list: ['刘亦菲', '火龙果', 'Leru']
            }
        },

        template: `
          <div>
          <slot v-for="item in list" :item="item" />
          </div>
        `
    })

动态组件

      const app = Vue.createApp({
        data() {
            return {
                showItem: 'dajiao'
            }
        },
        methods: {
            handleTrans() {
                this.showItem = this.showItem === "dajiao" ? 'liuying' : "dajiao"
            }
        },
        template: ` <h2>欢迎光几个菜啊-请选择您的朋友</h2>
        <keep-alive>
        <component :is="showItem"></component>
        </keep-alive>
        <button @click="handleTrans">切换</button>
        `
    })

  • <component :is=“showItem”/>指定显示哪一个组件
  • <keep-alive>启用了缓存,把input框的值存了起来,使用动态组件时,经常配合标签一起使用
  • <dajiao v-show=“showItem===‘dajiao’” /> 中v-show=控制是否显示

异步组件和Promise讲解

  • 必须使用Vue.defineAsyncComponent()声明
app.component('async-component',Vue.defineAsyncComponent(()=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve({
                template:`<div>这是一个异步组件</div>`
            })
        },3000)
    })

}))

provide和inject多级组件传值

  • 父模板
  • 数据项的下面声明一个provide
const app = Vue.createApp({
    data(){
        return {house:'北京别墅一套'}
    },
    provide:{
        newHouse:'北京200平方房子一套'
    },
    template: `
        <div>我有一套房子,我先传给我的儿子</div>
        <child :house="house" />
        `
})
  • 子模版
  • 用inject接收
app.component('child-child',{
    props:['house'],
    inject:['newHouse'],
    template:`
        <div>我是孙子,等待接收房子</div>
        <div>孙子接收{{house}},{{newHouse}}</div>
    `
})

动画

CSS样式中的动画效果

  • 创建一个CSS区域,然后编写样式。这时候我们要使用CSS中的animation属性,然后再使用关键帧keyframes指定详细的动画过程。
  • 样式
<style>
    .animation {
        animation: leftToRight 3s;
    }

    @keyframes leftToRight {
        0% {
            transform: translateX(0px);
        }

        25% {
            transform: translateX(25px);
        }

        50% {
            transform: translateX(50px);
        }

        75% {
            transform: translateX(25px);
        }

        100% {
            transform: translateX(0px);
        }

    }
</style>
  • 做一个数据项,这个数据项的作用就是控制动画起不起作用
  • 必须做成对象,直接使用animation无效
data() {
    return {
        isAnimate: {
            animation: false
        }
    }
},
  • 方法
methods: {
    handleClick() {
        this.isAnimate.animation = !this.isAnimate.animation
    }
  • 模板
 template: `  
            <div :class="isAnimate">Vue学习笔记</div>
            <div><button @click="handleClick">启动/关闭</button></div>
        `

Vue控制过渡效果

  • 样式
<style>
        .transition {
            /*过渡的事件 内容 过渡速度,具体见下表*/
            transition: 3s background-color ease;
        }

        .red {
            background-color: red;
        }

        .yellow {
            background-color: yellow;
        }
    </style>
  • transition 变化速度
描述
linear规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。(匀速)
ease规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezier(0.25,0.1,0.25,1))(相对于匀速,中间快,两头慢)。
ease-in规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))(相对于匀速,开始的时候慢,之后快)。
ease-out规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))(相对于匀速,开始时快,结束时候间慢,)。
ease-in-out规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))(相对于匀速,(开始和结束都慢)两头慢)。
cubic-bezier(n,n,n,n)在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。
  • 注意:数据驱动
data() {
    return {
        css: {
            transition: true,
            red: true,
            yellow: false
        }
    }
},
  • 方法
methods: {
    hanldClick() {
        this.css.red = !this.css.red
        this.css.yellow = !this.css.yellow

    }
},

Vue3制作过渡效果一

  • 样式
    <style>
        @keyframes comein {
            0% {
                transform: translateX(-150px)
            }
            100% {
                transform: translateX(0px)
            }
        }

        @keyframes comeout {
            0% {
                transform: translateX(0px)
            }
            100% {
                transform: translateX(-150px)
            }
        }

        /*固定的CSS样式写法v-enter-active意思是进入时采用何种动画方式*/
        .v-enter-active {
            animation: comein 1s;
        }
        /*固定的CSS样式写法v-leave-active意思是退出时采用何种动画方式*/
        .v-leave-active {
            animation: comeout 1s;
        }
    </style>

  • 过渡的类名 <transition>

    在进入/离开的过渡中,会有 6 个 class 切换。

 - v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
 - v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
 - v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter   被移除),在过渡/动画完成之后移除。
 - v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
 - v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
 - v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave   被删除),在过渡/动画完成之后移除。
  • 模板
  • 使用<transition>套在显示内容的外层,会自动加入动画效果
        template: `
          <transition><h3 v-show="isShow">Vue动画笔记</h3></transition>
          <button @click="handleClick">切换</button>
        `

Vue3制作过渡效果二

   .v-enter-from,.v-leave-to{
            opacity: 0;
        }
        .v-enter-to,.v-leave-from{
            opacity: 1;
        }

        .v-enter-active {
            transition: opacity 3s ease-out;
        }
        .v-leave-active {
            transition: opacity 3s ease-out;

        }

自定义标签一

<style>
        .chet-enter-active {
            animation: comein 1s;
        }
        .chet-leave-active {
            animation: comeout 1s;
        }
</style>
 template: `
          <transition name="chet"><h3 v-show="isShow">Vue动画笔记</h3></transition>
          <button @click="handleClick">切换</button>
        `

自定义标签二

<style>
        .come {
            animation: comein 1s;
        }
        .go {
            animation: comeout 1s;
        }
</style>
  template: `
          <transition enter-active-class="come"
                      leave-active-class="go"
          ><h3 v-show="isShow">Vue动画笔记</h3></transition>
          <button @click="handleClick">切换</button>
        `

第三方动画库Animate使用

  • 库标签
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
  />
  • 建议本地配置,下载地址https://github.com/animate-css/animate.css/releases
    <link  href="./animate.css"  rel="stylesheet" type="text/css"/>
  • 模板
 template: `
          <transition enter-active-class="animate__animated animate__bounce"
                      leave-active-class="animate__animated animate__flash"
          ><h3 v-show="isShow">Vue动画笔记</h3></transition>
          <button @click="handleClick">切换</button>
        `

过渡和动画协调

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Demo06</title>
    <style>
        @keyframes comein {
            0% {
                transform: translateX(-120px)
            }

            100% {
                transform: translateX(0px)
            }
        }

        @keyframes comeout {
            0% {
                transform: translateX(0px)
            }

            100% {
                transform: translateX(-120px)
            }
        }

        .v-enter-from,
        .v-leave-to {
            opacity: 0;
        }

        .v-enter-to,
        .v-leave-from {
            opacity: 1;
        }

        .v-enter-active {
            animation: comein 3s;
            transition: opacity 3s ease-out;
        }

        .v-leave-active {
            animation: comeout 3s;
            transition: opacity 3s ease-out;
        }
    </style>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.global.js"></script>
</head>

<body>
    <div id="app"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                isShow: false
            }
        },
        methods: {
            hanldClick() {
                this.isShow = !this.isShow
            }
        },
        template: `  
        <transition>
            <div v-if="isShow">技术胖讲程序</div>
        </transition>
        <button @click="hanldClick">切换动画</button>

        `
    })
    const vm = app.mount("#app")
</script>
  • 过渡和动画时长不一致的处理
  • 在标签上加入type='animation’属性,意思是不管过渡时长是多少,动画结束,整个过程结束。
template: `  
    <transition type="animation">
        <div v-if="isShow">技术胖讲程序</div>
    </transition>
    <button @click="hanldClick">切换动画</button>
`
  • 属性控制动画和过渡时长
  • 不管CSS中的动画和过渡时长,以标签为准。可以绑定属性 来控制时长,意思是1秒后,结束动画和过渡。
template: `  
    <transition :duration="1000">
        <div v-if="isShow">技术胖讲程序</div>
    </transition>
    <button @click="hanldClick">切换动画</button>
  • duration除了能写一个数字之外,还可以写对象进去,分别控制进入和退出时长
<transition :duration="{enter:1000,leave:3000}">

JS+Vue3制作动画和钩子函数

<script>
    const app = Vue.createApp({
        data() {
            return {
                isShow: false
            }
        },
        methods: {
            handleClick() {
                this.isShow = !this.isShow

            },
            handleBeforeEnter(element) {
                element.style.color = 'red'
            },
            handleEnterActive(element, done) {
                let interval = setInterval(() => {
                    let color = element.style.color;
                    if (color == 'red') {
                        element.style.color = "green"
                    } else {
                        element.style.color = "red"
                    }
                }, 500);
                setTimeout(() => {
                    clearInterval(interval)
                    done()
                }, 1500);

            },
             handleEnterEnd(element) {
                element.style.color = "blue"
            },
        },
        //js钩子函数
        //进入
        // @before-enter="handleBeforeEnter"
        // @enter="handleEnterActive"
        // @after-enter="handleEnterEnd"
        //退出
        // @before-leave=""
        // @leave=""
        // @leave-enter=""
        // :css="false"  关闭css动画
        template: `
          <transition :css="false"
                      @before-enter="handleBeforeEnter"
                      @enter="handleEnterActive"
                      @after-enter="handleEnterEnd"

          ><h3 v-show="isShow">Vue动画笔记</h3></transition>

          <button @click="handleClick">切换</button>
        `
    })
    const vm = app.mount("#app")
</script>

双DOM元素动画的实现

<style>
.v-enter-from,.v-leave-to{
    opacity: 0;
}
.v-enter-to,.v-leave-from{
    opacity: 1;
}
.v-enter-active,.v-leave-active{
    transition: opacity 2s ease-in;
}
    </style>

  • mode="out-in"先执行退出动画,再执行进入动画
  • appear刷新页面时执行进入动画
        template: `
          <transition mode="out-in" appear>
          <div v-if="isShow">大脚进入了电影院</div>
          <div v-else>晓红进入了电影院</div>
          </transition>
          <button @click="handleClick">切换动画</button>`

双组件切换动画的实现

  • 动态实现
<script>

//局部组件
    const Dajiao = {
        template: `
                  <div>大脚进入了电影院</div>
        `
    }
    const Xiaohong = {
        template: `
                  <div>晓红进入了电影院</div>
        `
    }
    const app = Vue.createApp({
        data() {
            return {
                isShow: false,
                component:'da-jiao'
            }
        },
        methods: {
            handleClick() {
                this.isShow = !this.isShow
                this.component=this.component==='da-jiao' ?'xiao-hong' : 'da_jiao'
            }
        },
        //注册局部组件
        components: {
            'da-jiao': Dajiao,
            'xiao-hong': Xiaohong
        },
        template: `
          <transition mode="out-in" appear>
<!--        //静态实现  <da-jiao v-if="isShow"/>-->
<!--       //   <xiao-hong v-else/>-->
          <component :is="component"></component>
          </transition>
          <button @click="handleClick">切换动画</button>`
    })
    const vm = app.mount("#app")
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值