# (Vue)MetroWidget
# 1.基本介绍
MetroWidget组件用于 JsView-Vue3 架构。 该组件提供自动排布和焦点管理功能
# 2.控件说明
props、可调用函数,以及item template的属性说明,以代码包(tgz)的MetroWidget.vue的头信息为准。
路径:
node_modules/@shijiu/jsview-vue/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue
# 3.技巧展示
插槽如何使用?
- 插槽属性参见slotProp
提问: item的onFocus/onBlur和JsvFocusBlock的onFocus/onBlur有何区别?
- 整个MetroWidget在焦点树上只有一个节点, 既MetroWidget内部只有一个<jsv-focus-block/>, props中的onFocus/onBlur对应这个JsvFocusBlock
- item的onFocus/onBlur对应的是MetroWidget自身内部状态的改变
按键是怎么处理的?
- 上下左右键已经由控件接管,不需要开发者处理。
- 通过注册onClick回调来处理用户的OK键动作。
- 其他按键组件不会处理, 按JsvFocusBlock统一的冒泡处理
焦点到达边缘后怎么离开此组件?
- 当焦点移动到控件边缘时,会调用onEdge回调。在回调中通过参数传递的值来决定焦点转移的行为
# 4.示例搭建
# demo.vue
- 前置操作
import { MetroWidget, HORIZONTAL, // 定义MetroWidget方向的Symbol EdgeDirection, // MetroWidget onEdge回调中的方向比对 useFocusHub, } from "jsview"; import { onMounted } from "vue"; import Item from "./Item.vue" // 描画item的组件 const focusHub = useFocusHub(); // mounted后设置焦点 onMounted(() => { focusHub.setFocus(name); })
1
2
3
4
5
6
7
8
9
10
11
12
13 - template中添加MetroWidget组件
<template> <metro-widget :name="name" :left="widgetLayout.left" :top="widgetLayout.top" :width="widgetLayout.width" :height="widgetLayout.height" :provideData="provideData" :direction="HORIZONTAL" :measures="measures" :onEdge="onEdge" > </metro-widget> </template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14 - 在script中定义MetroWidget所需的prop
//组件的焦点ID const name = "widget" //组件的布局信息 const widgetLayout = { left: 50, top: 50, width: 300, height: 200, } //提供数据的回调 const provideData = () => { const data = []; for (let i = 0; i < 30; i++) { data.push({ width: 90, height: 90, marginRight: 10, marginBottom: 10, color: "#00DD00", content: i, }); } return data; } // 提供item布局信息的回调 const measures = (data) => { return { width: data.width, height: data.height, marginRight: data.marginRight, marginBottom: data.marginBottom, }; }; //组件到达边缘时的回调 const onEdge = (edgeInfo) => { if (edgeInfo.direction == EdgeDirection.top) { console.log("top edge"); } else { console.log("other side edge") } }
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
41 - 添加MetroWidget的slot, 并在slot中描画item
<template> <metro-widget ... > <template #renderItem="{ data, onAction }"> <item :data="data" :onAction="onAction" /> </template> </metro-widget> </template>
1
2
3
4
5
6
7
8
9 - 全部代码
<script setup> import { MetroWidget, HORIZONTAL, // 定义MetroWidget方向的Symbol EdgeDirection, // MetroWidget onEdge回调中的方向比对 useFocusHub, } from "jsview"; import Item from "./Item.vue" import { onMounted } from "vue"; const focusHub = useFocusHub(); // mounted后设置焦点 onMounted(() => { focusHub.setFocus(name); }); //组件的焦点ID const name = "widget"; //组件的布局信息 const widgetLayout = { left: 50, top: 50, width: 300, height: 200, }; //提供数据的回调 const provideData = () => { const data = []; for (let i = 0; i < 30; i++) { data.push({ width: 90, height: 90, marginRight: 10, marginBottom: 10, color: '#00DD00', content: i, }); } return data; }; // 提供item布局信息的回调 const measures = (data) => { return { width: data.width, height: data.height, marginRight: data.marginRight, marginBottom: data.marginBottom, }; }; //组件到达边缘时的回调 const onEdge = (edgeInfo) => { if (edgeInfo.direction == EdgeDirection.top) { console.log("top edge"); } else { console.log("other side edge"); } }; </script> <template> <metro-widget :name="name" :left="widgetLayout.left" :top="widgetLayout.top" :width="widgetLayout.width" :height="widgetLayout.height" :provideData="provideData" :direction="HORIZONTAL" :measures="measures" :onEdge="onEdge" > <template #renderItem="{ data, onAction }"> <item :data="data" :onAction="onAction" /> </template> </metro-widget> </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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# item.vue
- 主要操作
- 根据数据描画内容
- 向onAction对象注册回调
- 在回调中更改自身状态
- 全部代码
<script setup> import { ref, shallowRef, inject } from "vue"; const props = defineProps({ data: Object, onAction: Object, }); const focused = ref(false); //在回调中更改自身状态 const onFocus = () => { focused.value = true; }; const onBlur = () => { focused.value = false; }; const onClick = () => { console.log("item onclick ", props.data); }; // 注册回调 props.onAction.register("onFocus", onFocus); props.onAction.register("onBlur", onBlur); props.onAction.register("onClick", onClick); </script> <template> <div :style="{ width: data.width, height: data.height, fontSize: 30, color: focused ? '#FF0000' : '#FFFFFF', backgroundColor: data.color, }" > {{ data.content }} </div> </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
29
30
31
32
33
34
35
36
37
38