暗黑模式
响应式
前端Vue.js响应式
传递响应式对象到渲染函数
Vue2
vue
<template>
<button @click="onClick">点击</button>
</template>
<script>
import { MessageBox } from "element-ui";
import SomeCompoment from "./SomeCompoment.vue";
export default {
data() {
return {
reactiveObj: {
prop1: 1, // 只有声明了属性之后,Vue 才会把这个属性设置为响应式的,参考源代码 `defineReactive`,原理是给 reactiveObj 添加了 prop1 的 getter 和 setter
prop2: 2, // 同上
},
};
},
methods: {
onClick() {
const h = this.$createElement;
// this.$set(this.reactiveObj, "prop1", 'val1'); // 如果在初始化 reactiveObj 时没有显示声明 prop1 属性,还可以通过 Vue.set 来动态添加响应式的 prop1
// this.$set(this.reactiveObj, "prop2", 'val2'); // 同上
// const reactiveObj = new Vue({ data() { return { prop1: 1, prop2: 2 } } }) // 这种方式也可以
const VNode = h(SomeCompoment, {
props: {
myObj: this.reactiveObj, // prop1 和 prop2 都是响应式的,在 SomeComponent.vue 中修改后会触发 UI 更新
},
});
MessageBox.confirm(VNode, "提示");
setInterval(() => {
this.reactiveObj.prop1++; // 会响应式更新 SomeComponent.vue
this.reactiveObj.prop2--; // 同上
}, 1000);
},
},
};
</script>
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
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
vue
<template>
<div>
<input v-model="myObj.prop1" />
<input v-model="myObj.prop2" />
</div>
</template>
<script>
export default {
props: {
myObj: {
type: Object,
},
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue3
vue
<script setup lang="ts">
import { ref, reactive, h } from "vue";
import { ElMessageBox } from "element-plus";
import SomeComponent from "./SomeComponent.vue";
function onClick() {
const myObj = reactive({ prop1: 1, prop2: 2 }); // 也可以使用 ref({ prop1: 1, prop2: 2 })
const myVal = ref(3);
const VNode = h(SomeComponent, {
myObj,
myVal, // 注意:此次传入的是 Ref<number> 对象
});
ElMessageBox.confirm(VNode, "提示");
setInterval(() => {
myObj.prop1++; // 会响应式更新 SomeComponent.vue
myObj.prop2--; // 同上
myVal.value++; // 同上
}, 1000);
}
</script>
<template>
<button @click="onClick">点击</button>
</template>
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
vue
<script setup lang="ts">
defineProps<{
myObj: { prop1: number; prop2: number };
myVal: Object; // Ref<number>
}>();
</script>
<template>
<div>
<input v-model="myObj.prop1" />
<input v-model="myObj.prop2" />
<!-- myVal 是 Ref<number>,所以使用 myVal.value -->
<input v-model="myVal.value" />
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue3 进阶
要想使非对象的变量保持响应性,可以使用以下方法:VNode → Render Function
vue
<script setup lang="ts">
import { ref, h } from "vue";
import { ElMessageBox } from "element-plus";
import SomeComponent from "./SomeComponent.vue";
function onClick() {
let myVal = ref(1);
const VNodeRenderFunc = () =>
h(SomeComponent, {
myVal: myVal.value,
"onUpdate:myVal"(val) {
myVal.value = +val;
},
}); // 渲染函数会被执行多次,每次返回的 VNode 都使用最新的 myVal.value
ElMessageBox.confirm(VNodeRenderFunc, "提示").then(() => {
alert(myVal.value);
});
setInterval(() => {
myVal.value++; // 会响应式更新 SomeComponent.vue
}, 1000);
}
</script>
<template>
<button @click="onClick">点击</button>
</template>
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
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
vue
<script setup lang="ts">
defineProps<{
myVal: number;
}>();
const emit = defineEmits(["update:myVal"]);
</script>
<template>
<input :value="myVal" @input="emit('update:myVal', $event.target.value)" />
</template>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11