02 Vue 组件
loyalvi Lv7

02 Vue组件

组件

  • 组件的定义
  • 组件具备复用性
  • 全局组件,只要定义了,处处可以使用,性能不高,但是使用起来简单,名字建议 小写字母单词,中间用横线间隔
  • 局部组件,定义了,要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大些字母开头,驼峰命名
  • 局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue 底层也会自动尝试帮你做映射
    全局组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//全局组件,只要定义了,处处可以使用,性能不高,但是使用起来简单,名字建议 小写字母单词,中间用横线间隔
const app = Vue.createApp({
template: `
<div>
<counter-parent />
<counter />
</div>
`
});
app.component('counter-parent', {
template: `<counter />`
})
app.component('counter', {
data() {
return {
count: 1
}
},
template: `<div @click="count += 1">{{count}}</div>`
})
const vm = app.mount('#app');

局部组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//局部组件,定义了,要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大些字母开头,驼峰命名
//局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue 底层也会自动尝试帮你做映射
const Counter = {
data() {
return {
count: 1
}
},
template: `<div @click="count += 1">{{count}}</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');

组件传值

父->子

  • 父组件标签的值 子组件props接收(静态传参)
1
2
3
4
5
6
7
const app = Vue.createApp({
template: ` <div><test content="123" /></div>`
});
app.component('test', {
props: ['content'],
template: `<div>{{content}}</div>`
});
  • 父组件标签的值 子组件props接收(动态)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const app = Vue.createApp({
data() {
return { num: 1234 }
},
template: `
<div><test :content="num" /></div>
`
});
// type:String, Boolean, Array, Object, Function, Symbol
// required 必填
// default 默认值
// validator 校验
app.component('test', {
props: {
content: {
type: Number,
validator: function(value) {
return value < 1000;
},
default: function() {
return 456;
}
}
},
template: `<div>{{content}}</div>`
});

多参数

1
2
// v-bind="params"
// :content="params.content" :a="params.a" :b="params.b" :c="params.c"

传接变量

1
2
3
// 属性传的时候,使用 content-abc 这种命名,接的时候,使用 contentAbc 命名
//content-abc->contentAbc
//标签里content-abc命名 props里小驼峰接

单项数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 单项数据流的概念: 子组件可以使用父组件传递过来的数据,但是绝对不能修改传递过来的数据
const app = Vue.createApp({
data() {
return { num: 1 }
},
template: `
<div>
<counter :count="num" />
<counter :count="num" />
<counter :count="num" />
</div>
`
});
app.component('counter', {
props: ['count'],
template: `<div @click="count += 1">{{count}}</div>`
});

None-prop

  • 子组件不适用props接受父组件的传值,子组件渲染时,直接把传值放在标签上,显示在DOM里
  • 子组件不用props时,可以用v-bind="$attrs"获取值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Non-prop 属性
const app = Vue.createApp({
template: `
<div>
<counter msg="hello" msg1="hello1" />
</div>
`
});
app.component('counter', {
// inheritAttrs: false,
mounted() {
console.log(this.$attrs.msg);
},
template: `
<div :msg="$attrs.msg">Counter</div>
<div v-bind="$attrs">Counter</div>
<div :msg1="$attrs.msg1">Counter</div>
`
});

事件通信

触发事件驼峰,监听事件-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const app = Vue.createApp({
data() {
return { count: 1 }
},
methods: {
handleAddOne() {
this.count++
}
},
//监听事件-
template: `
<counter v:count="count" @add-one="handleAddOne"/>
`
});
app.component('counter', {
props: ['count'],
//事件列表,也可以在这判断筛选
emits:['addOne','add2','update'],
methods: {
handleClick() {
//触发事件驼峰
this.$emit('addOne');
}
},
template: `
<div @click="handleClick">{{count}}</div>
`
});

v-model 双向数据绑定来实现通信
来回入参命名固定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const app = Vue.createApp({
data() {
return { count: 1 }
},
template: `
<counter v-model="count" />
`
});
app.component('counter', {
props: ['modelValue'],
methods: {
handleClick() {
this.$emit('update:modelValue', this.modelValue + 3);
}
},
template: `
<div @click="handleClick">{{modelValue}}</div>
`
});

给别名:app,多个值给多个别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const app = Vue.createApp({
data() {
return { count: 1 }
},
template: `
<counter v-model:app="count" />
`
});
app.component('counter', {
props: ['app'],
methods: {
handleClick() {
this.$emit('update:app', this.modelValue + 3);
}
},
template: `
<div @click="handleClick">{{app}}</div>
`
});

给v-model添加自定义修饰符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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>
`
});

插槽slot和具名插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// slot 插槽
// slot 中使用的数据,作用域的问题
// 父模版里调用的数据属性,使用的都是父模版里的数据
// 子模版里调用的数据属性,使用的都是子模版里的数据
// 具名插槽 v-slot:header 等价于 #header
const app = Vue.createApp({
template: `
<layout>
<div>slot</div>
</layout>
<layout2>
<template v-slot:header>
<div>header</div>
</template>
<template v-slot:footer>
<div>footer</div>
</template>
</layout2>
`
});
app.component('layout', {
template: `
<div>
<slot></slot>
</div>
`
});
app.component('layout2', {
template: `
<div>
<slot name="header"></slot>
<div>content</div>
<slot name="footer"></slot>
</div>
`
});

作用域插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 作用域插槽
const app = Vue.createApp({
template: `
<list v-slot="{item}">
<div>{{item}}</div>
</list>
`
});
app.component('list', {
data() {return {list: [1, 2, 3]}},
template: `
<div>
<slot v-for="item in list" :item="item" />
</div>
`
});

动态组件和异步组件

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 动态组件:根据数据的变化,结合component标签来随时动态切换组件
const app = Vue.createApp({
data(){
return{
currentItem:"input-item"
}
},
template: `
//缓存
<keep-alive>
<component :is="input-item">
</keep-alive>
`
});
app.component('word-item', {
template: `
hello
`
});
app.component('input-item', {
template: `
<input/>
`
});

异步组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 异步组件: 是异步执行某些组件的逻辑,这叫做异步组件
const app = Vue.createApp({
template: `
<div>
<common-item />
<async-common-item />
</div>
`
});
app.component('common-item', {
template: `<div>hello world</div>`
});
app.component('async-common-item', Vue.defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
template: `<div>this is an async component</div>`
})
}, 4000)
})
}))
由 Hexo 驱动 & 主题 Keep
访客数 访问量