Vue组件—进阶篇


提示:以下是本篇文章正文内容,下面案例可供参考

一、组件 — 组件上使用v-model

1. v-model双数据绑定:

默认情况下,在组件上使用v-model绑定的是modelValue属性,数据改变触发的是 update:modelValue 事件;

app.component('my-input',{
    props:['modelValue'],
    emits:['update:modelValue'],
    template:`
        <input type="text" :value="modelValue" @input="$emit("update:modelValue",$event.target.value)">
    `
})

使用组件时就可以传递默认值,也就完成了双向数据绑定,数据改变dom跟着改变,dom改变数据跟着改变。

<my-input v-model="msg"></my-input>

当然,默认传递的属性名称是可以改变的:

<my-input v-model:age="msg"></my-input>

那么与之对应的组件也要跟着调整

app.component('my-input',{
    props:['age'],
    emits:['update:age'],
    template:`
        <input type="text" :value="age" @input="$emit('update:age',$event.target.value)">
    `
})

一个组件上可以使用多个数据绑定!

在这里插入图片描述
在组件内做好对应的接收,以及绑定队友的数据改变事件就可以了,这里就不演示了。

2. v-model 修饰符:

果直接在组件上使用v-model内置的修饰符,修饰符不会生效;vue3.X版本提供了组件自定义修饰符功能。

	添加到组件 v-model 的修饰符将通过 modelModifiers 属性提供给组件的prop;

也就是说,需要我们自己去定义修饰符的具体逻辑!

app.component('my-input',{
    props:{
        modelValue:null,
        modelModifiers:null
    },
    emits:['update:modelValue'],
    template:`
        <input type="text" :value="modelValue" @input="$emit('update:modelValue',$event.target.value)">
    `,
    created(){
        console.log(this.modelModifiers);
    }
})

传递到子组件的 modelModifiers 属性会在实例创建好时,生成一个包含验证规则为true的对象;
上面代码的结果,如下图:
在这里插入图片描述

有了这些关键信息,就可以在组件中触发事件时,根据修饰符的true、false处理相关的业务逻辑
true代表你写了该修饰符,那就生效对应的逻辑,如去除首位空格,只能输入数字等。

这里有我练习的时候写的一些小例子,想看的可以看一下,用的时候别用中文输入法,当时写的很潦草,O(∩_∩)O

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../bootstrap/css/bootstrap.min.css">
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        ul{
            list-style: none;
        }
        .box{
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="container">
            {{info}}
            <br>
            <my-input v-model.number="info"></my-input>
        </div>
    </div>
</body>  
<script src="../bootstrap/js/jquery.min.js"></script>
<script src="../bootstrap/js/bootstrap.min.js"></script>
<script src="../vue.global.js"></script>
<script>
    let app = Vue.createApp({
        data(){
            return {
                info:123,
            }
        },
        methods:{
            change(e){
                console.log(e);
            }
        }
    })
    app.component('my-input',{
        template:`
            <input class="form-control" type="text" @input="change" :value="modelValue">
        `,
        // inheritAttrs:false,
        emits:['update:modelValue'],
        props:{
            modelValue:null,
            modelModifiers:null
        },
        data(){
            return{
            }
        },
        methods:{
            change(e){
                let reg = /^[0-9]*$/g
                let result = e.target.value;
                if( this.modelModifiers && this.modelModifiers.number ){
                    if( !reg.test(result) ){
                        result = result.substring(0,result.length-1)
                        e.target.value = result;
                    }
                }
                this.$emit('update:modelValue',result)
            }
        }
    })
    
    app.mount('#app')
</script>
</html>

二、组件 — 插槽

1. 插槽:

Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。
当使用组件时,可能更希望的是在组件标签中写入内容,实现动态展示不同内容的功能;

		<my-input>文字</my-input>
        <my-button>按钮</button>
        <my-div>盒子</my-div>

也就是让我们的自定义组件看起来跟真的组件一样。

	默认情况下,如果组件标签中没有包含一个 <slot> 元素,
	则该组件起始标签和结束标签之间的任何内容都会被抛弃	。
	所以,可以通过在组件中添加<slot>标签实现分发内容的目的
<my-btn>自定义按钮</my-btn>

app.component('my-btn',{
    template:`
        <button>
            <slot></slot>     
        </button>
    `
})

插槽可以定义默认值

app.component('my-btn',{
    template:`
        <button>
            <slot>不写,我就显示啦!</slot>     
        </button>
    `
})

2. 具名插槽:

	给<slot>标签添加name属性,以声明当前插槽的名称

在这里插入图片描述

	在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,
	并以 v-slot 的参数的形式提供其名称:

在这里插入图片描述

	现在 <template> 元素中的所有内容都将会被传入相应的插槽。
	注意:在使用具名插槽时,其分发内容的指令v-slot必须写在template标签上;

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #;

在这里插入图片描述

三、组件 — 深层组件传值

在这里插入图片描述
如何使用 prop 把 my-main 的值传递到 my-btn?

很简单,在父级或以上级别的组件使用 provide 把一个值暴露出来。

然后,在需要使用值的子级或一下级别的组件使用 inject 引入该值就可以了

在这里插入图片描述

四、组件 — 动态组件

有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里,类似 tab切换的效果。
动态组件可以通过 Vue 的 元素加一个特殊的 is 来实现;

<component :is="currentCom"></component>

const currentCom = {
    template:`
        <div>
            <p>这是一个组件示例</p>
        </div>
    `
}

如果在某一个组件中定义一个文本框,输入内容之后,如果发生切换行为,会发现文本框中的内容消失了

在这里插入图片描述
这是因为你每次切换组件的时候,Vue 都创建了一个新的组件实例。
每次都创建新的组件是非常有用的,比如每次切换都需要获取新的新闻内容,但是,有的时候是需要记录上次状态的,如果有这样的需求可以通过 keep-alive 标签来完成

<keep-alive>
    <component :is="show"></component>
</keep-alive>

在这里插入图片描述

keep-alive的Vue的官方解释,包裹动态组件时,会缓存不活动的组件页面,

我们可以借此来完成,保留组件状态,避免重新渲染。

这个小练习的完整代码我放在下面了,有需要的可以看一看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../bootstrap/css/bootstrap.min.css">
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        ul{
            list-style: none;
        }
        .box{
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="container">
            <button @click="show='my-input'">input</button>
            <button @click="show='my-p'">p</button>
            <button @click="show='my-span'">span</button>
            <button @click="show='my-text'">text</button>
            <br>
            <keep-alive>
                <component :is="show"></component>
            </keep-alive>
        </div>
    </div>
</body>  
<script src="../bootstrap/js/jquery.min.js"></script>
<script src="../bootstrap/js/bootstrap.min.js"></script>
<script src="../vue.global.js"></script>
<script>
    let app = Vue.createApp({
        data(){
            return {
                show:'my-input',
            }
        },
        methods:{
            change(e){
                console.log(e);
            }
        },
        provide:{
            cont:111,
        }
    })
    app.component('my-input',{
        template:`
            <div class="panel panel-success">
                <div class="panel-heading">
                    标题
                 </div>
                <div class="panel-body">
                    asdasdasd
                </div>
            </div>
        `,
        // inheritAttrs:false,
        emits:['update:modelValue'],
        props:{
            modelValue:null,
        },
        data(){
            return{
            }
        },
        methods:{
        }
    })
    app.component('my-p',{
        template:`
            <p>
                这是一个p标签
                <my-span></my-span>
            </p>
        `
    })
    app.component('my-span',{
        template:`
            <span>
                    这是一个span
            </span>
        `,
    })
    app.component('my-text',{
        template:`
            <input type='text'>
        `,
    })
    
    app.mount('#app')
</script>
</html>

总结

以上就是vue组件进阶篇的所有内容,关于组件的知识点还有很多,如果大家想进一步更深入的了解组件的更多知识,可以去Vue的官网进行更全面的了解。
我更希望本篇文章,能给一些刚学习vue的人带来逻辑思路上的灵感,本人也是一名新人,欢迎大家多多指教!

  • 35
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值