文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
一、组件 — 组件上使用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的人带来逻辑思路上的灵感,本人也是一名新人,欢迎大家多多指教!