Vue基础入门(中)

news2024/11/18 22:48:10

组件的定义

组件具备复用性 注意:全局组件,只要定义了,处处可以使用,性能不高,但是使用起来简单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 14</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    const app = Vue.createApp({
        template:`
        <div><count-parent/></div>
        <div><count/></div>
        <div><count/></div>
        `
    });

    app.component('count-parent',{
        template:`<count/>`
    })

    app.component('count',{
        data(){
            return{
                count:1
            }
        },
        template:`<div @click="count+=1">{{count}}</div>`
    })
    const vm=app.mount('#root');
</script>

</html>

 与其对应的还有局部组件

const counter={
        data(){
            return{
                counter:1
            }
        },
        template:`
            <div @click="counter+=1">{{counter}}</div>
        `
    }
    const app = Vue.createApp({
        components:{'counter':counter},
        template:`
            <div><counter/></div>
        `
    });

    const vm=app.mount('#root');

解释:单引号'counter'代表组件名字,也可随意命名,但是为了见名其意,建议使用变量名(es6语法中在key和value一样时可以只写counter即可) 

通常我们会这样写,代码如下

const Counter={
        data(){
            return{
                counter:1
            }
        },
        template:`
            <div @click="counter+=1">{{counter}}</div>
        `
    }

    const HelloWorld={
        template:`<div>hello world</div>`
    }
    const app = Vue.createApp({
        components:{
            //counter:Counter,
            //'hello-world':HelloWorld
            Counter,
            HelloWorld
        },
        template:`
            <div>
                <hello-world/>
                <counter/>
            </div>
        `
    });

    const vm=app.mount('#root');

 说明:局部组件定义了,要注册之后才能使用,性能比较高,但是使用起来麻烦,建议大写字母开头,驼峰命名法(注意:局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue底层也会自动尝试帮你做映射

静态动态传参区别 

子组件展示的内容不是固定的,而是父组件在调用子组件的时候给它传递动态的内容(注意:想要内容123是数字型,我们给他赋予动态传参v-bind:content,而content仅仅只是静态传参

const app = Vue.createApp({
        data(){
            return {
                num:123
            }
        },
        template:`
            <div>
                <test :content="num"/>
            </div>
        `
    });

    app.component('test',{
        props:['content'],
        template:`<div>{{typeof content}}<div>`
    });
    const vm=app.mount('#root');

const app = Vue.createApp({
        data(){
            return {
                num:()=>{
                    alert(123);
                }
            }
        },
        template:`
            <div>
                <test :content="num"/>
            </div>
        `
    });
//    String,Boolean,Array,Object,Function
    app.component('test',{
        props:{'content':Function},
        methods:{
            handleClick(){
                alert(456);
                this.content();
            }
        },
        template:`<div @click="this.handleClick">{{typeof content}}<div>`
    });
    const vm=app.mount('#root');

 

 const app = Vue.createApp({
        data(){
            return {
                num:123
            }
        },
        template:`
            <div>
                <test/>
            </div>
        `
    });

    // required 必须传值
    // default 默认值
    // validation 验证
    app.component('test',{
        props:{
            content:{
                type:Number,
                validation:function(value){
                    return value<1000;
                },
                default:function(){
                    return 456;
                }
            }
        },
        
        template:`<div>{{content}}</div>`
    });
    const vm=app.mount('#root');

 当遇到子组件需要传递很多参数的时候,可以考虑使用精简的语法v-bind="params"

// v-bind="params"等价于
    // :content="params.content" :a="params.a" :b="params.b" :c="params.c"
    const app = Vue.createApp({
        data() {
            return {
                params:{
                    content: 1234,
                    a: 123,
                    b: 456,
                    c: 789
                }
            }
        },
        template: `
            <div>
                <test :content="params.content" :a="params.a" :b="params.b" :c="params.c"/>
            </div>
        `
    });

    app.component('test', {
        props: ['content', 'a', 'b', 'c'],
        template: `<div>{{content}}-{{a}}-{{b}}-{{c}}</div>`
    });
    const vm = app.mount('#root');

特殊语法:属性传的时候,使用content-abc这种命名,接的时候,使用contentAbc命名

const app = Vue.createApp({
        data() {
            return {
                content:123
            }
        },
        template: `
            <div>
                <test :content-abc="content"/>
            </div>
        `
    });

    app.component('test', {
        props: ['contentAbc'],
        template: `<div>{{contentAbc}}</div>`
    });
    const vm = app.mount('#root');

单项数据流:子组件可以使用父组件传递过来的数据,但是不能修改(想要修改的话得使用自己的属性赋值)

const app = Vue.createApp({
        data() {
            return {
                num:1
            }
        },
        template: `
            <div>
                <counter :count="num"/>
            </div>
        `
    });

    app.component('counter', {
        props: ['count'],
        data(){
            return{
                myCount:this.count
            }
        },
        template: `<div @click="myCount+=1">{{myCount}}</div>`
    });
    const vm = app.mount('#root');

Non-props属性

const app = Vue.createApp({
        template: `
            <div>
                <counter msg="hello"/>
            </div>
        `
    });

    app.component('counter', {
        template: `
            <div>Count</div>
        `
    });
    const vm = app.mount('#root');

 加了inheritAttrs属性设置为false就没有其msg属性了

app.component('counter', {
        inheritAttrs:false,
        template: `
            <div>Count</div>
        `
    });

$attrs作用(把父组件传递过来的所有属性都放到该标签里)

const app = Vue.createApp({
        template: `
            <div>
                <counter msg="hello" msg1="hello1"/>
            </div>
        `
    });

    app.component('counter', {
        mounted(){
            console.log(this.attrs.msg);
        },
        template: `
            <div v-bind:msg="$attrs.msg">Count</div>
            <div v-bind="$attrs">Count</div>
            <div :msg1="$attrs.msg1">Count</div>
        `
    });
    const vm = app.mount('#root');

 

触发外面事件 this.$emit()

const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        methods:{
            handleAddOne(){
                return this.count+=1;
            }
        },
        template: `
            <div>
                <counter :count="count" @add-one="handleAddOne"/>
            </div>
        `
    });

    app.component('counter', {
        props:['count'],
        emits:['addOne'],
        methods:{
            handleClick(){
                this.$emit('addOne');
            }
        },
        template: `
            <div @click="handleClick">{{count}}</div>
        `
    });
    const vm = app.mount('#root');

emits验证是否可以往外传不会报错只会警告 

const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        methods:{
            handleAdd(count){
                this.count=count;
            }
        },
        template: `
            <div>
                <counter :count="count" @add="handleAdd"/>
            </div>
        `
    });

    app.component('counter', {
        props:['count'],
        emits:{
            add:(count)=>{
                if(count>10){
                    return true;
                }
                return false;
            }
        },
        methods:{
            handleClick(){
                this.$emit('add',this.count+3);
            }
        },
        template: `
            <div @click="handleClick">{{count}}</div>
        `
    });
    const vm = app.mount('#root');

高级东西(了解一下)

const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        template: `
            <div>
                <counter v-model="count"/>
            </div>
        `
    });

    app.component('counter', {
        props:['modelValue'],
        methods:{
            handleClick(){
                this.$emit('update:modelValue',this.modelValue+3)
            }
        },
        template: `
            <div @click="handleClick">{{modelValue}}</div>
        `
    });
    const vm = app.mount('#root');
const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        template: `
            <div>
                <counter v-model:app="count"/>
            </div>
        `
    });

    app.component('counter', {
        props:['app'],
        methods:{
            handleClick(){
                this.$emit('update:app',this.app+3)
            }
        },
        template: `
            <div @click="handleClick">{{app}}</div>
        `
    });
    const vm = app.mount('#root');

选修课(较难)

拼接字符串且转换为大写形式(自定义修饰符:modelModifiers)

const app = Vue.createApp({
        data() {
            return {
                count: 'a'
            }
        },
        template: `
            <counter v-model.uppercase="count"/>
        `
    });

    app.component('counter', {
        props: {
            'modelValue': String,
            'modelModifiers': {
                default: () => ({})
            }
        },
        methods: {
            handleClick() {
                let newValue = this.modelValue + 'b';
                if (this.modelModifiers.uppercase) {
                    newValue = newValue.toUpperCase();
                }
                this.$emit('update:modelValue', newValue);
            }
        },
        template: `
            <div @click="handleClick">{{modelValue}}</div>
        `
    });
    const vm = app.mount('#root');

slot插槽

传递dom节点或者标签就可以使用插槽 

父模板里调用的数据属性,使用的都是父模板里的数据

子模板里调用的数据属性,使用的都是子模板里的数据

const app = Vue.createApp({
        data(){
            return{
                text:'提交'
            }
        },
        template: `
            <myform>
                <div>{{text}}</div>    
            </myform>
            <myform>
                <button>{{text}}</button>    
            </myform>
        `
    });

    app.component('myform', {
        methods:{
            handleClick(){
                alert(123);
            }
        },
        template: `
            <input/>
            <span @click="handleClick">
                <slot></slot>
            </span>
        `
    });
    const vm = app.mount('#root');

具名插槽(拆分插槽)

简写形式#header相当于v-slot:header

const app=Vue.createApp({
        template:`
            <layout>
            <template v-slot:header>
                <div>header</div>    
            </template>
            <template v-slot:footer>
                <div>footer</div>
            </template>
            </layout>
        `
    });

    app.component('layout',{
        template:`
            <slot name="header"></slot>
            <div>content</div>
            <slot name="footer"></slot>
        `
    });

    const vm=app.mount('#root');

插槽高级语法

作用域插槽(写Vue插件常用)

const app=Vue.createApp({
        template:`
            // <list v-slot="slotProps">
            //     <div>{{slotProps.item}}</div>    
            // </list>
            <list v-slot="{item}">
                <div>{{item}}</div>    
            </list>
        `
    });

    app.component('list',{
        data(){
            return{
                list:[1,2,3]
            }
        },
        template:`
            <slot v-for="item in list" :item="item"/>
        `
    });

    const vm=app.mount('#root');

说明:首先父组件去调用list子组件,这一块<div>{{slotProps.item}}</div>就是传递给子组件的slot,在子组件去循环内容的时候,去调用slot意思就是通过<div></div>这种形式去展示内容,但是,我在调用slot的时候把数据传给slot(把item这些数据传给slot)然而slot怎么接收呢?它通过v-slot=“slotProps”这样的一个数据对象(传递过来的所有内容都放在这个对象中),接收了之后,这就可以使用传递过来的item内容(当子组件渲染的内容要由父组件决定的时候

Vue动态组件 

 根据数据的变化,结合component这个标签,来随时动态切换组件的现实

const app = Vue.createApp({
        data() {
            return {
                currentItem: 'input-item'
            }
        },
        methods: {
            handleClick() {
                this.currentItem = this.currentItem === 'input-item' ? 'common-item' : 'input-item';
            }
        },
        template: `
            <keep-alive><component :is="currentItem"/></keep-alive>
            <button @click="handleClick">切换</button>
        `
    });

    app.component('input-item', {
        template: `
            <input/>
        `
    });

    app.component('common-item', {
        template: `
            <div>hello world</div>
        `
    });
    const vm = app.mount('#root');

Vue异步组件

是异步执行某些组件的逻辑,这叫异步组件

const app = Vue.createApp({
        template: `
            <common-item />
            <asyncComponent />
        `
    });
    app.component('common-item', {
        template: `
            <div>hello world</div>
        `
    });
    app.component('asyncComponent', Vue.defineAsyncComponent(() => {
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve({
                    template:`<div>this is an async component</div>`
                })
            },4000)
        });
    })
    );
    const vm = app.mount('#root');

v-once和ref 

v-once 让某个元素标签只渲染一次
ref 实际上是获取dom节点/组件引用的一个语法 


    const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        mounted(){
            this.$refs.common.sayHello();
        },
        template: `
            <div>
                <common-item ref="common"/>
            </div>
        `
    });

    app.component('common-item',{
        methods:{
            sayHello(){
                alert('hello');
            }
        },
        template:`<div>hello world</div>`
    })
    
    const vm = app.mount('#root');

 显示hello world之前弹出hello

provide/inject跨多级值的传递

const app = Vue.createApp({
        data(){
            return{
                count:1
            }
        },
        // provide:{
        //     count:1
        // },
        provide(){
            return{
                count:this.count,
            }
        },
        template: `
            <div>
                <child :count="count"/>
            </div>
        `
    });

    app.component('child',{
        template:`<child-child/>`
    })

    app.component('child-child',{
        inject:['count'],
        template:`<div>{{count}}</div>`
    })

    const vm = app.mount('#root');

 注意:count变化provide里面的东西不会跟着变化,只渲染一次

动画

transform:translateX 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 23</title>
    <style>
        @keyframes leftToRight {
            0% {
                transform: translateX(-100px);
            }

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

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

        .animation {
            animation: leftToRight 3s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                animate: {
                    animation: true
                }
            }
        },
        methods: {
            handleClick() {
                this.animate.animation = !this.animate.animation;
            }
        },
        template: `
            <div :class="animate">hello world</div>
            <button @click="handleClick">切换</button>
        `
    });

    const vm = app.mount('#root');
</script>
</html>

过渡

transition 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 23</title>
    <style>
        /* @keyframes leftToRight {
            0% {
                transform: translateX(-100px);
            }

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

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

        .animation {
            animation: leftToRight 3s;
        } */

        .transition{
            transition: 3s background-color ease;
        }

        .blue{
            background-color: blue;
        }

        .green{
            background-color: green;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                animate: {
                    transition:true,
                    blue:true,
                    green:false
                }
            }
        },
        methods: {
            handleClick() {
                if(this.animate.blue){
                    this.animate.blue=!this.animate.blue;
                    this.animate.green=!this.animate.green;
                }else{
                    this.animate.blue=!this.animate.blue;
                    this.animate.green=!this.animate.green;
                }
            }
        },
        template: `
            <div :class="animate">hello world</div>
            <button @click="handleClick">切换</button>
        `
    });

    const vm = app.mount('#root');
</script>
</html>

 也可以下面这样写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 23</title>
    <style>
        .transition{
            transition: 3s background-color ease;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                styleObj:{
                    background:'blue'
                }
            }
        },
        methods: {
            handleClick() {
                if(this.styleObj.background==='blue'){
                    this.styleObj.background='green';
                }else{
                    this.styleObj.background='blue';
                }
            }
        },
        template: `
            <div class="transition" :style="styleObj">hello world</div>
            <button @click="handleClick">切换</button>
        `
    });

    const vm = app.mount('#root');
</script>
</html>

单元素单组件的入场出场过渡动画 

过渡 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 24</title>
    <style>
        .v-enter-from{
            opacity: 0;
        }
        .v-enter-active,.v-leave-active{
            transition: opacity 3s ease-out;
        }
        .v-enter-to{
            opacity: 1;
        }
        .v-leave-to{
            opacity: 0;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show=!this.show;
            }
        },
        template: `
            <div>
                <transition>
                    <div v-if="show">hello world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>
</html>

动画 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 24</title>
    <style>
        @keyframes shake {
            0%{
                transform: translateX(-100px);
            }
            50%{
                transform: translateX(-50px);
            }
            100%{
                transform: translateX(50px);
            }
        }
        .v-enter-active,
        .v-leave-active{
            animation: shake 3s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show=!this.show;
            }
        },
        template: `
            <div>
                <transition>
                    <div v-if="show">hello world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>
</html>

如果我们给它命名的话<transition name="hello"></transition>,那么style里面的v-enter-from这些都需要换为hello-enter-from

引入第三方样式库

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link
        rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
    />
    <title>lesson 24</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    // v-show隐藏还是会占用div的
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show=!this.show;
            }
        },
        template: `
            <div>
                <transition
                    enter-active-class="animate__animated animate__flash"
                    leave-active-class="animate__animated animate__flash"
                >
                    <div v-show="show">hello world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>
</html>

过渡和动画相结合 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 24</title>
    <style>
        @keyframes shake {
            0%{
                transform: translateX(-100px);
            }
            50%{
                transform: translateX(-50px);
            }
            100%{
                transform: translateX(50px);
            }
        }
        .v-enter-from{
            color: red;
        }
        .v-enter-active{
            animation: shake 3s;
            transition: color 3s ease-in;
        }
        /*动画从红变黑,再由黑变红*/
        .v-leave-active{
            animation: shake 3s;
            transition: color 3s ease-in;
            color: red;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    // v-show隐藏还是会占用div的
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show=!this.show;
            }
        },
        template: `
            <div>
                <transition>
                    <div v-show="show">hello world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>
</html>

当动画和过渡时间不一致时,可以在<transition type="animation"></transition>标签中添加type属性,表示以动画时间为准,当不想以css中设置时间来响应,可以在<transition :duration="{enter:1000,leave:3000}"></transition>标签中添加duration属性

使用js来处理动画和过渡 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 24</title>
    <style>
        /* @keyframes shake {
            0%{
                transform: translateX(-100px);
            }
            50%{
                transform: translateX(-50px);
            }
            100%{
                transform: translateX(50px);
            }
        }
        .v-enter-from{
            color: red;
        }
        .v-enter-active{
            animation: shake 10s;
            transition: color 3s ease-in;
        }
        .v-leave-active{
            animation: shake 10s;
            transition: color 3s ease-in;
            color: red;
        } */
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    // v-show隐藏还是会占用div的
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show = !this.show;
            },
            handleBeforeEnter(el) {
                el.style.color = "red";
            },
            handleEnterActive(el, done) {
                const animation = setInterval(() => {
                    const color = el.style.color;
                    if (color === 'red') {
                        el.style.color = 'green';
                    } else {
                        el.style.color = 'red';
                    }
                }, 1000);
                setTimeout(() => {
                    clearInterval(animation);
                    done();
                }, 3000);
            },
            handleEnterEnd(){
                alert(123);
            }
        },
        template: `
            <div>
                <transition
                  :css="false"
                  @before-enter="handleBeforeEnter"
                  @enter="handleEnterActive"
                  @after-enter="handleEnterEnd"
                >
                    <div v-show="show">hello world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

多个单元素标签切换先隐藏再出现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 25</title>
    <style>
        .v-enter-from,
        .v-leave-to{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s ease-in;
        }
        .v-enter-to,
        .v-leave-from{
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 单元素,单组件的出场入场动画
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show = !this.show;
            },
            
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <div v-if="show">hello world</div>
                    <div v-else="show">bye world</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

多个单元素组件切换先隐藏再出现一

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 25</title>
    <style>
        .v-enter-from,
        .v-leave-to{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s ease-in;
        }
        .v-enter-to,
        .v-leave-from{
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 多个单组件之间的切换
    const ComponentA={
        template: `<div>hello world</div>`
    }
    const ComponentB={
        template: `<div>bye world</div>`
    }
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
            handleClick() {
                this.show = !this.show;
            },
            
        },
        components:{
            'component-a':ComponentA,
            'component-b':ComponentB,
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <component-a v-if="show"/>
                    <component-b v-else="show"/>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

多个单元素组件切换先隐藏再出现二

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 25</title>
    <style>
        .v-enter-from,
        .v-leave-to{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s ease-in;
        }
        .v-enter-to,
        .v-leave-from{
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 多个单组件之间的切换
    const ComponentA={
        template: `<div>hello world</div>`
    }
    const ComponentB={
        template: `<div>bye world</div>`
    }
    const app = Vue.createApp({
        data() {
            return {
                component: 'component-a'
            }
        },
        methods: {
            handleClick() {
                if(this.component==='component-a'){
                    this.component='component-b';
                }else{
                    this.component='component-a';
                }
            },
            
        },
        components:{
            'component-a':ComponentA,
            'component-b':ComponentB,
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <component :is="component"/>
                </transition>
                <button @click="handleClick">切换</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

列表动画的实现 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 26</title>
    <style>
        .v-enter-from{
            opacity: 0;
            transform: translateY(30px);
        }
        .v-enter-active{
            transition: all .5s ease-in;
        }
        .v-enter-to{
            opacity: 1;
            transform: translateY(0px);
        }
        .list-item{
            display: inline-block;
            margin-right: 10px;
        }
        .v-move{
            transition: all .5s ease-in;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 列表动画的实现
    const app = Vue.createApp({
        data() {
            return {
                list:[1,2,3]
            }
        },
        methods: {
            handleClick() {
                this.list.unshift(this.list.length+1);
            },
            
        },
        template: `
            <div>
                <transition-group>
                    <span class="list-item" v-for="item in list" :key="item">{{item}}</span>
                </transition-group>
                <button @click="handleClick">增加</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

状态动画的实现 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 26</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="root"></div>
</body>
<script>
    // 状态动画的实现
    const app = Vue.createApp({
        data() {
            return {
                number: 1,
                animateNumber: 1
            }
        },
        methods: {
            handleClick() {
                this.number = 10;
                if (this.animateNumber < this.number) {
                    const animation = setInterval(() => {
                        this.animateNumber += 1;
                        if (this.animateNumber === 10) {
                            clearInterval(animation);
                        }
                    }, 100);
                }
            },

        },
        template: `
            <div>
                <div>{{animateNumber}}</div>
                <button @click="handleClick">增加</button>
            </div> 
        `
    });

    const vm = app.mount('#root');
</script>

</html>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/541710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下的用户分类与su/sudo 命令,Linux下的文件类型/用户文件权限身份/文件权限属性/权限与文件权限/ls-l文件属性详解

Tips 下载就是把我们的文件拷贝到系统的某个特定路径之下&#xff0c;普通用户是不允许你往系统里面去拷的。 Linux下的用户分类 root用户&#xff0c;管理员级别的用户身份&#xff0c;他的话基本上不受权限的约束。普通用户&#xff0c;普通用户的添加与每个普通用户密码的…

《面试1v1》JavaNIO

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 面试官&#xff1a; 你好&#xff0c;我想问一下你对 Java NIO 的了解。 候选人&#xff1a; 当然&#xff0c;Java NIO 是 Java 的一种 I/O 模型&#xff0c;它提…

MapReduce【自定义分区Partitioner】

实际开发中我们可能根据需求需要将MapReduce的运行结果生成多个不同的文件&#xff0c;比如上一个案例【MapReduce计算广州2022年每月最高温度】&#xff0c;我们需要将前半年和后半年的数据分开写到两个文件中。 默认分区 默认MapReduce只能写出一个文件&#xff1a; 因为我…

「OceanBase 4.1 体验」OceanBase:解读领先的分布式数据库系统,功能与体验全解析

文章目录 前言一、关于 【OceanBase 4.1】征文活动&#xff08;可跳过&#xff09;二、OceanBase 产品了解2.1 初识 OceanBase2.2 什么是 OceanBase2.3 OceanBase 相关链接2.4 OceanBase 与传统数据库对比有何特别之处2.5 OceanBase 相关概念以及术语2.5.1 OceanBase 基本概念2…

接口测试总结及其用例设计方法整理,希望可以帮到你

目录 接口测试的总结文档 第一部分&#xff1a; 第二部分&#xff1a; 接口测试用例设计 接口测试的总结文档 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做…

ios中video标签兼容问题

案例 这是在实际开发中遇到的问题,产品给出的效果图如下: 其实就是一个h5页面中有很多视频, 但是我为什么都画着预览图呢? 因为在ios中video标签中尽管有src属性, 但是在没有预览图的情况下, 是一个灰蒙蒙的图层的, 很丑, 效果如下: 看到这里是不是很崩溃, 在PC端, 在安卓端…

RK3568平台开发系列讲解(Camera篇)快速了解RK Camera的使用

🚀返回专栏总目录 文章目录 一、MIPI CSI1.1 Full Mode特点1.2 Split Mode特点二、Full Mode配置2.1 配置sensor端2.2 csi2_dphy0相关配置2.3 isp相关配置三、Split Mode配置3.1 配置sensor端3.2 csi2_dphy1/csi2_dphy2相关配置3.3 isp相关配置四、软件相关目录

自然语言处理实战项目7-利用层次聚类方法做文本的排重,从大量的文本中找出相似文本

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目7-利用层次聚类方法做文本的排重&#xff0c;从大量的文本中找出相似文本。随着互联网技术的不断发展&#xff0c;越来越多的数据被广泛地应用在各个领域中。而文本数据是其中之一&#xff0c;…

ar在汽车维修行业的应用场景

由于AR增强现实技术的易用性&#xff0c;在汽车产业链中&#xff0c;已处处可见AR技术的踪影&#xff0c;像汽车设计AR远程协同&#xff0c;汽车装配AR远程指导&#xff0c;汽车维修AR远程协助等等&#xff0c;那么下面为详细介绍AR增强现实技术在汽车制造领域的应用。 环境/物…

实力在线 | 赛宁网安连续三年入选《中国网络安全市场全景图》

​​近日&#xff0c;国内专业安全机构数说安全正式发布了《2023年中国网络安全市场全景图》&#xff08;以下简称全景图&#xff09;。此次全景图分类架构涵盖了产品、解决方案、应用场景、服务4个维度&#xff0c;覆盖了目前我国网络安全行业所有成熟的细分市场。 赛宁网安凭…

Postman实现数字签名,Session依赖, 接口依赖, 异步接口结果轮询

Script(JS)为Postman赋予无限可能 基于Postman 6.1.4 Mac Native版 演示结合user_api_demo实现 PS 最近接到任务, 要把几种基本下单接口调试和持续集成一下, 做个常规功能验证, 研究了下发现, 不同的下单途径, 有的需要登录(Session依赖), 有的需要验签(使用数字签名的微服务),…

用本地机做跳板使服务器连接外网【mac】

用自己的电脑做跳板使服务器连接外网 前提整体流程连接服务器配置服务器配置自己的电脑 前提 很多时候我们的服务器只能联内网&#xff0c;但是没法登外网&#xff0c;这样pip&#xff0c;conda 啥的都没法用&#xff0c;很麻烦。 一个简单的解决方法就是用自己的电脑作为跳板…

补充点【数据分析统计学知识点】

数据分析所需的统计学笔记 0.数据分析师拿到数据 第一利器&#xff1a;描述性统计信息 第二利器&#xff1a;对比分析法 第三利器&#xff1a;指标体系-要素拆解&#xff0c;维度拆解 第四利器&#xff1a;相关分析 第五利器&#xff1a;趋势预测 1.均值 2.中位数 3.众数…

基于Java+SpringBoot+vue的口腔管家平台设计与实现

博主介绍&#xff1a;擅长Java、微信小程序、Python、Android等&#xff0c;专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例…

Hadoop 3.0.0的集群搭建和Hive 3.1.3的安装

Hi,朋友们&#xff0c;我们又见面了&#xff0c;这一次我给大家带来的是Hadoop集群搭建及Hive的安装。 说明一下&#xff0c;网上有很多的教程&#xff0c;为什么我还要水&#xff1f; 第一&#xff0c;大多数的安装都是很顺利的&#xff0c;没有疑难解答。 第二&#xff0c…

分布式项目08 redis的扩容,预备redis宕机的哨兵处理 和 最后集大成redis集群

01.redis扩容 由于redis的容量也是有限的&#xff0c;所以&#xff0c;就会有扩容的操作。也就好像内存中扩容一样。redis有分片这种说法&#xff0c;具体实现操作如下&#xff1a; 第一步&#xff1a;首先在/usr/local/src中去找到redis文件夹。cd /usr/local/src 而后进入re…

瑞吉外卖 - 菜品信息分页查询功能(17)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

开源大语言模型完整列表

Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 LLM 通常基于神经网络模型&#xff0c;使用大规模的语料库进行训练&#xff0c;比如使…

【Linux进阶之路】基本指令(下)

文章目录 一. 日志 date指令——查看日期基本语法1基本语法2cal指令——查看日历常见选项 二 .find——查找文件常用选项-name显示所有文件显示指定类型的文件 三.grep——行文本过滤工具语法常见的用法补充知识——APP与服务器的联系 四.打包压缩与解压解包zip与unzipzipunzip…

又一高速AD/DA数据采集卡问世,何不了解一下?

FMC190 子卡集成 2 通道 3Gsps 采样率&#xff0c;14 位 AD&#xff0c;2 通道12.8Gsps 16 位DA。板载时钟芯片 HMC7044&#xff0c;可以提供JESD204B所需要的各种时钟。具有同步/触发功能&#xff0c;模拟信号采用 SSMA 射频连接器输入和输出。板载时钟芯片为 HMC7044&#xf…