NT_1_Vue

Compute计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- CustomInput.vue -->
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
computed: {
newvalue() {'
return value + "1"
}
value: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
}
}
}
}
</script>

对于newvalue,当value变化时,newvalue也会跟着变化。value实现了组件v-model的功能。

在Comp上使用v-model

1
2
3
4
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>

<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>

透传标签属性

class, id等在父组件上定义的都会被头传到子组件。@click也会。

click 监听器会被添加到 <MyButton>根元素,即那个原生的 <button> 元素之上。当原生的 <button> 被点击,会触发父组件的 onClick 方法。同样的,如果原生 button 元素自身也通过 v-on 绑定了一个事件监听器,则这个监听器和从父组件继承的监听器都会被触发。

禁用:在组件选项中设置 inheritAttrs: false

透传进来的 attribute 可以在模板的表达式中直接用 $attrs 访问到。
包含了除组件所声明的 props 和 emits 之外的所有其他 attribute,例如 class,style,v-on 监听器等等。

插槽Slot

1
2
3
<FancyButton>
Click me! <!-- 插槽内容 -->
</FancyButton>
1
2
3
4
5
<button class="fancy-btn">
<slot>
默认内容
</slot> <!-- 插槽出口 -->
</button>
  • 插槽可以是任何模板内容(元素、甚至是组件)
  • 插槽内容只能访问到父作用域。

具名插槽

没有提供name属性的slot出口会隐式地命名为default。

父组件声明v-slot名称作为slot的name。

1
2
3
4
5
父组件
<div class="container">
<header v-slot="hi">
</header>
</div>
1
2
子组件
<div name="hi"></div>

v-slot可以缩写为#

动态插槽

v-slot内的内容可以是js变量。v-slot:[dynamicSlotName]

作用域插槽

分为具名和不具名。

v-slot内可以使用解构。

依赖注入

提供方:

1
2
3
4
5
6
provide() {
// 使用函数的形式,可以访问到 `this`
return {
message: this.message
}
}

上面的是非响应式的。要换成响应式,用计算属性

1
message: computed(() => this.message)

注入方:

1
2
3
4
5
6
 export default {
inject: ['message'],
created() {
console.log(this.message) // injected value
}
}

注入方可以使用别名注入,在使用别名注入时,也可以设置默认值
1
2
3
4
5
6
inject: {
/* 本地属性名 */ localMessage: {
from: /* 注入来源名 */ 'message',
default : 'default value'
}
}

异步组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const AsyncComp = defineAsyncComponent({
// 加载函数
loader: () => import('./Foo.vue'),

// 加载异步组件时使用的组件
loadingComponent: LoadingComponent,
// 展示加载组件前的延迟时间,默认为 200ms
delay: 200,

// 加载失败后展示的组件
errorComponent: ErrorComponent,
// 如果提供了一个 timeout 时间限制,并超时了
// 也会显示这里配置的报错组件,默认值是:Infinity
timeout: 3000
})

Logical Reuse

组合式函数

1
2
3
4
// 按照惯例,组合式函数名以“use”开头
export function usexxxx() {
//xxxxxxx
}

其他组件中

1
import { usexxxx } from './xxx.js'

支持组合函数嵌套。

自定义指令

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
37
38
39
40

//method1
const focus = {
mounted: (el) => el.focus()
}

export default {
directives: {
// 在模板中启用 v-focus
focus
}
}

<input v-focus />



//method2 全局
const app = createApp({})
// 使 v-focus 在所有组件中都可用
app.directive('focus', (el, binding) => {
/* ... */
})


//指令钩子
el:指令绑定到的元素。这可以用于直接操作 DOM。

binding:一个对象,包含以下属性。
//<div v-demo="{ color: 'white', text: 'hello!' }"></div>
//返回的binding就是其中定义的对象
value:传递给指令的值。例如在 v-my-directive="1 + 1" 中,值是 2。
oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 "foo"。
modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
instance:使用该指令的组件实例。
dir:指令的定义对象。
vnode:代表绑定元素的底层 VNode。

prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

不用钩子函数的话,直接在callback内写,将会mounted和updated时调用

插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// plugins/xxx.js
export default {
install: (app, options) => {
// 注入一个全局可用的 $hello() 方法
app.config.globalProperties.$hello = (val) => {
// codes
}
}
}

//注册
import x'x'x from './plugins/xxx'

app.use(i18nPlugin, {
//额外参数 options
})

//使用
$hello('val')

插件也可使用provide()来在整个应用层面提供依赖:

1
app.provide('xxx', xxx)

内置组件

Transition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button @click="show = !show">Toggle</button>
<Transition>
<p v-if="show">hello</p>
</Transition>

.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
opacity: 0;
}