本文已参与「新人创作礼」活动,一起开启掘金创作之路
定义与使用组件
定义组件
一个*.vue文件就是一个组件,组件名可以使用 kebab-case风格命名,也可以用 camelCase风格命名。组件内容Vue 组件框架保持一致
组件使用
import <组件在本文件中的名字> from '组件相对位置'
再通过components属性把引用的组件列举出来,即可在<template>中直接当作组件使用
<script >
import Button from './Comp.vue'
export default {
components:{Button}
}
</script>
组件的样式
style样式
组件样式Style
scoped:限定组件样式应用范围
默认情况下,组件style里的样式描述是全局可用的。 在组件<style>中添加 scoped 后 (<style scoped>),样式描述仅限本组件
<style scoped>
.button{
...
}
.button:active{
...
}
</style>
组件的数据传递
探讨数据的流向
props:Vue组件的属性
从父组件传递数据到子组件,使用子组件的props属性。
props是一个属性,里面每一个对象定义的内容是可以直接在 <template/> 上使用的data。每个对象里面有 type和default的值
//子组件中
<template>
<button class="button">
{{text}}
</button>
</template>
<script >
export default {
props:{
// text为 data 的名字
text:{
type: String,
default:'按钮',
}
}
</script>
在子组件中定义了props属性后,可以在父组件用相应的属性名传递数据
//父组件中
<script >
import Button from './Comp.vue'
export default {
...
components:{
Button
}
}
</script>
<template>
<Button text="确认" />
</template>
监听子组件的事件
父组件可以监听子组件的自定义事件,并作出相应反应。子组件可以通过自定义事件告诉父组件发生的事情
创建自定义事件
$emit('tap',text) 第一个参数为名称,第二个参数为传递的值
//子组件中
<template>
//定义了一个点击后发生的自定义事件
<button class="button" @click="$emit('tap',text)">
{{text}}
</button>
</template>
<script>
export default{
...
created(){
//定义了一个创建后发生的自定义事件
this.$emit('init')
}
}
</script>
监听自定义事件
在父组件中可以监听子组件中创建的事件,监听时发生了自定义事件,则在父组件可以指定方法做点事
// 父组件中
<script >
import Button from './Comp.vue'
export default {
...
methods:{
//参数为子组件定义时传来的数据
onTapAppButton(text){
console.log('on tap app button', text)
},
onInitAppButton(){
console.log('on init app button')
}
},
components:{
Button
}
}
</script>
<template>
//当发生 子组件定义的tap事件时,触发onTapAppButton()方法
<Button @tap="onTapAppButton" @init="onInitAppButton" text="好了" />
</template>
在自定义组件上使用 v-model
ninghao.co/T5mILy 建议再看一遍
组件间可以使用v-model进行数据的双向绑定。
//父组件
<script >
import Input from './Input.vue'
export default {
data(){
return{
value:""
}
},
components:{Input}
}
</script>
<template>
// 以下两种写法等值
// :modelValue="value" 通过 props从父传递至子 ; @update:modelValue 通过自定义事件从子传递至父
<Input :modelValue="value" @update:modelValue="value = $event"/>
<Input v-model="value"/>
{{value}}
</template>
需要在子组件定义好自定义事件和props属性,名称需要固定才能直接在父组件用 v-model绑定
//子组件
<template>
// @input 当输入事件发生时,创建自定义事件 update:modelValue
// :value 输入框内的值绑定 props的 modelValue
<input type="text" :value="modelValue" @input="$emit('update:modelValue',$event.target.value)" >
</template>
<script>
export default{
props:{
modelValue:{
type:String
}
}
}
</script>
组件的生命周期
组件会在相应周期执行周期函数内的内容
<script>
export default{
//...
beforeCreate(){
console.log('comp beforeCreat')
},
created(){
console.log('comp created')
}
// mounted() beforeMount()
// updated() beforeUpdata()
// unmounted() beforeUnmount()
}
</script>
其余
slot
在父组件中直接为子组件插入任何HTML内容
//子组件
<template>
<button>
// 定义插槽的位置
<slot></slot>
</button>
</template>
//父组件
<template>
// 组件内输入的内容会放置在插槽中
<Input> hello </Input>
</template>
动态组件
通过条件确定渲染哪一个组件,可通过事件更换组件
<component :is="compName"></component> 中 :is 是需要渲染的组件
<script >
import Login from './userLogin.vue'
import Register from './userRegister.vue'
export default {
data(){
return{
compName:"Login",
hit:"没有账号?立即注册"
}
},
methods:{
change(){
// 通过条件切换组件
switch(this.compName){
case 'Login':
this.compName = 'Register'
this.hit = "已有账号,立即登陆"
break
case 'Register':
this.compName = 'Login'
this.hit = "没有账号?立即注册"
break
}
}
},
components:{Login,Register}
}
</script>
<template>
<component :is="compName"></component>
<small @click="change">{{hit}}</small>
</template>
keep-alive
切换组件时,里面的内容会丢失。如果需要保持内容不丢失,可以使用 <keep-alive> 把动态组件包装起来
<template>
// 里面的组件切换过程中不会被销毁
<keep-alive>
<component :is="compName"></component>
</keep-alive>
<small @click="change">{{hit}}</small>
</template>
$refs:引用模板
像在代码中直接操作某个HTML元素,可以使用$refs设置id,并且通过id进行相关操作.
<template>
<input type="text" ref="username">
</template>
<script>
export default{
...
mounted(){
console.log(this.$refs.username)
this.$refs.username.focus()
}
}
</script>