文章目录
一、组件 — 如何注册组件?
1.全局注册:
vue实例是最大的根组件,在它上面注册组件就是全局注册,全局组件在任何组件实例中都可以使用
在学习使用组件之前,我们先来学习怎么注册组件
const app = Vue.createApp({...})
app.component('my-component-name',{
/*组件主体*/
})
‘my-component-name’ 是你要定义的组件名称。
组件名称有两种风格:
kebab-case (my-button)(推荐)
PascalCase (MyButton)
然后通过template属性可以定义组件的具体结构样式,示例如下:
app.component('my-component-name',{
template:`
<div>
<h1>这是一个自定义组件</h1>
</div>
`
})
app.mount('#app')
这里要注意一个细节,组件注册一定要在根组件挂载(虚拟dom绑定真实dom) 之前,而且不能用链式操作,而且最好保证只存在一个根节点
2.局部注册:
局部注册组件通过在实例中使用components属性注册:
<body>
<div id="app">
<my-component-name>1</my-component-name>
</div>
</body>
//下面是js代码,省略了<script>标签
let app = Vue.createApp();
const MyBtn = {
template:`
<button>按钮</button>
`
}
app.component('my-component-name',{
template:`
<div>
<h1>这是一个自定义组件</h1>
<my-btn>
</div>
`,
components:{
'my-btn':MyBtn
}
})
app.mount('#app')
局部注册组件推荐的方式
3.全局注册与局部注册组件的总结:
全局注册的组件可以在全局组件或者局部组件中使用
局部注册的组件不能被其他组件使用;除非你把局部组件又注册到其他组件中
注册号的组件可以像一个普通标签一样,重复使用
组件接受与 Vue.createApp 相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等
别忘了,最大的根组件就是vue实例,所以在vue实例中的方法和属性,在组件中同样可以使用,它们一模一样
重复使用组件时,每个组件都会维护自己的属性,因为你每用一次组件,就会有一个它的新实例被创建,也就是说,它的生命周期钩子会被重新触发!
二、组件 — prop
1. 通过 Prop 向子组件传递数据:
组件提供一个props属性,专门用来接受你在使用组件时,写在组件身上的属性(标签属性)的属性
<my-btn title="标题"></my-btn>
app.component('my-btn',{
props:['title'],
template:`
<div>
<p>{{title}}</p>
</div>
`
})
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop(静态绑定)如上示例
当然, 也可以使用 v-bind 来动态传递 prop。(动态态绑定)如下示例
<ul>
<li v-for="item in list" :key="item.new_id">
<my-btn new_id="item.new_id"></my-btn>
</li>
</ul>
app.component('btn',{
props:['new_id'],
template:`
<div>
<h1>{{new_id}}</h1>
</div>
`
})
props接收到的属性的使用方式,跟data中的一模一样,但props 只能读,不能改!!
当然,无论是静态绑定还是动态绑定都遵循单向数据流规则:
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,
但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
而且在传递引用数据类型(对象,数组……)的数据时,它传递的仅仅是一个指向数据存放位置的指针,这时候,如果去改变它的值,则父级组件中的数据也会发生改变!
所以,传递引用类型的时候,容易造成数据流向的不确定性(尽量避免)
2.prop类型:
在接收prop数据时,有时你可能想要约束传递来的数据类型,以方便后续的逻辑操作
前面的键名是你要接收的自定义属性,后面是类型约束,规定必须传此类型的值,否则会报错
props:{
titile:String,
count:Number,
yn:Boolean,
myobj:Object,
myarr:Array
},
当然,你不仅可以约束数据类型,同时还可以设置一些其他的约束:
props:{
mycontext:{
type:[String,Number], // 类型约束
request:true, // 是否必填
default:'你不传值,我生效', // 默认值
},
myobj:{
type:Object, // 类型约束是对象或数组类型时,必须定义一个工厂函数
default:()=>{
return{ msg:'hello' }
}
}
},
3.prop验证:
通过定义prop类型,可以完成类型上的检测;当然,除了类型检测,prop还可以完成一些其他的验证:
mytext:{
type:String,
//自定义验证函数,通过validator来定义
validator: (value) => {
let reg = /^[A-Z]\w*$/g;
// 返回值为true,表示验证通过;
return reg.test(value)
}
}
4.非prop属性
没有在组件内通过props接受的属性 – 即非props属性
当组件返回单个根节点时(组件中的所有元素包含在一个根节点中),
非 prop 属性将自动添加到根节点的属性中,这种现象称为属性继承;
<my-btn class="box" type="pirmary"></my-btn>
let app = Vue.createApp({})
const Mydiv = {
porps:['type'],
template:`
<div v-bind:type="type"></div>
`
}
app.component('my-div',Mydiv)
app.mount('#app')
通过属性继承这一特性,我们可以让自定义组件更像真实的标签,可以直接给它添加class样式。
当然,你可以在组件的选项中设置 inheritAttrs: false,禁用属性继承;
同时你也可以通过,组件的 $attrs 属性来获取props 和 emits 属性中未包含的其他属性;
let app = Vue.createApp({})
const Mydiv = {
porps:['type'],
inheritAttrs: false, // 设置此属性后,根组件将不再自动继承非prop属性
template:`
<div v-bind:type="$attrs.type"></div>
`
}
app.component('my-div',Mydiv)
app.mount('#app')
三、组件— 自定义事件
1.首先,给组件绑定自定义事件
首先,在组件标签上自定义一个事件:(自定义事件的名字随意,推荐使用kebab-case格式)
<my-btn @myclick="change"></my-btn>
绑定自定义事件之后,就可以在组件内接收,跟prop接收自定义属性一样,这里通过emits接收(声明)事件;
app.component('my-btn',{
emits:['myclick'],
template:`
<button>自定义组件</button>
`
})
2.然后,在组件内绑定普通事件
在组件内先绑定你要触发的普通事件(js原生事件方法),然后通过 $emit() 方法触发接收到的自定义事件
这里一定要注意: $emit()是vue实例的一个方法,跟上面的提到 emits 完全不是一回事,不要搞混了!
app.component('my-btn',{
emits:['myclick'],
template:`
<button @click="say">自定义组件</button>
`,
methods:{
say(){
this.$emit('myclick')
}
}
})
$emit(‘自定义事件’,‘可选性的传递第二个参数’);
第二个参数会直接传递到父组件的methods方法中,所以就像接收普通参数一样使用就可以;
注意:如果自定义事件不是一个函数,而是一段js逻辑,可以通过$emit()的第二个参数传值,但是接收时,直接通过 $event接收(只能接受一个参数);
自定义事件可以完成子组件传值到父组件
总结:
以上就是vue组件基础篇的所有内容,大家通过练习就可以轻松学会并掌握组件的基础知识和用法。
下一篇 vue组件进阶篇,将会讲述关于vue组件的其他知识点。