Ing*_*ler 7 vue.js vuejs3 vue-composition-api
这是我在 Tabs 组件中使用 VUE 2 的旧代码:
created() {
this.tabs = this.$children;
}
Run Code Online (Sandbox Code Playgroud)
标签:
<Tabs>
<Tab title="tab title">
....
</Tab>
<Tab title="tab title">
....
</Tab>
</Tabs>
Run Code Online (Sandbox Code Playgroud)
VUE 3:如何使用组合 API 在 Tabs 组件中获取有关儿童的一些信息?获取长度,迭代它们,并创建标签页眉,......等等?有任何想法吗?(使用组合 API)
哦,伙计们,我解决了它:
slots.default().filter(child => child.type.name === 'Tab')
Run Code Online (Sandbox Code Playgroud)
我扫描子元素的解决方案(在对 vue 代码进行了大量筛选之后)是这样的。
export function findChildren(parent, matcher) {
const found = [];
const root = parent.$.subTree;
walk(root, child => {
if (!matcher || matcher.test(child.$options.name)) {
found.push(child);
}
});
return found;
}
function walk(vnode, cb) {
if (!vnode) return;
if (vnode.component) {
const proxy = vnode.component.proxy;
if (proxy) cb(vnode.component.proxy);
walk(vnode.component.subTree, cb);
} else if (vnode.shapeFlag & 16) {
const vnodes = vnode.children;
for (let i = 0; i < vnodes.length; i++) {
walk(vnodes[i], cb);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将返回子组件。我对此的用途是我有一些通用的对话框处理代码,用于搜索子表单元素组件以查询其有效性状态。
const found = findChildren(this, /^(OSelect|OInput|OInputitems)$/);
const invalid = found.filter(input => !input.checkHtml5Validity());
Run Code Online (Sandbox Code Playgroud)
现在这是我的 Vue 3 组件。我使用提供来获取子Tab组件中的信息。
<template>
<div class="tabs">
<div class="tabs-header">
<div
v-for="(tab, index) in tabs"
:key="index"
@click="selectTab(index)"
:class="{'tab-selected': index === selectedIndex}"
class="tab"
>
{{ tab.props.title }}
</div>
</div>
<slot></slot>
</div>
</template>
<script lang="ts">
import {defineComponent, reactive, provide, onMounted, onBeforeMount, toRefs, VNode} from "vue";
interface TabProps {
title: string;
}
export default defineComponent({
name: "Tabs",
setup(_, {slots}) {
const state = reactive({
selectedIndex: 0,
tabs: [] as VNode<TabProps>[],
count: 0
});
provide("TabsProvider", state);
const selectTab = (i: number) => {
state.selectedIndex = i;
};
onBeforeMount(() => {
if (slots.default) {
state.tabs = slots.default().filter((child) => child.type.name === "Tab");
}
});
onMounted(() => {
selectTab(0);
});
return {...toRefs(state), selectTab};
}
});
</script>
Run Code Online (Sandbox Code Playgroud)
标签组件:
export default defineComponent({
name: "Tab",
setup() {
const index = ref(0);
const isActive = ref(false);
const tabs = inject("TabsProvider");
watch(
() => tabs.selectedIndex,
() => {
isActive.value = index.value === tabs.selectedIndex;
}
);
onBeforeMount(() => {
index.value = tabs.count;
tabs.count++;
isActive.value = index.value === tabs.selectedIndex;
});
return {index, isActive};
}
});
<div class="tab" v-show="isActive">
<slot></slot>
</div>
Run Code Online (Sandbox Code Playgroud)
如果你复制粘贴与我相同的代码
然后只需向“tab”组件添加一个创建的方法,该方法将自身添加到其父级的 tabs 数组中
created() {
this.$parent.tabs.push(this);
},
Run Code Online (Sandbox Code Playgroud)
通过脚本设置语法,您可以使用useSlots:https://vuejs.org/api/sfc-script-setup.html#useslots-useattrs
<script setup>
import { useSlots, ref, computed } from 'vue';
const props = defineProps({
perPage: {
type: Number,
required: true,
},
});
const slots = useSlots();
const amountToShow = ref(props.perPage);
const totalChildrenCount = computed(() => slots.default()[0].children.length);
const childrenToShow = computed(() => slots.default()[0].children.slice(0, amountToShow.value));
</script>
<template>
<component
:is="child"
v-for="(child, index) in childrenToShow"
:key="`show-more-${child.key}-${index}`"
></component>
</template>
Run Code Online (Sandbox Code Playgroud)
对于想要完整代码的人:
标签页
<template>
<div>
<div class="tabs">
<ul>
<li v-for="tab in tabs" :class="{ 'is-active': tab.isActive }">
<a :href="tab.href" @click="selectTab(tab)">{{ tab.name }}</a>
</li>
</ul>
</div>
<div class="tabs-details">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "Tabs",
data() {
return {tabs: [] };
},
created() {
},
methods: {
selectTab(selectedTab) {
this.tabs.forEach(tab => {
tab.isActive = (tab.name == selectedTab.name);
});
}
}
}
</script>
<style scoped>
</style>
Run Code Online (Sandbox Code Playgroud)
Tab.vue
<template>
<div v-show="isActive"><slot></slot></div>
</template>
<script>
export default {
name: "Tab",
props: {
name: { required: true },
selected: { default: false}
},
data() {
return {
isActive: false
};
},
computed: {
href() {
return '#' + this.name.toLowerCase().replace(/ /g, '-');
}
},
mounted() {
this.isActive = this.selected;
},
created() {
this.$parent.tabs.push(this);
},
}
</script>
<style scoped>
</style>
Run Code Online (Sandbox Code Playgroud)
应用程序.js
<template>
<Tabs>
<Tab :selected="true"
:name="'a'">
aa
</Tab>
<Tab :name="'b'">
bb
</Tab>
<Tab :name="'c'">
cc
</Tab>
</Tabs>
<template/>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4228 次 |
| 最近记录: |