封装索引列表
效果
直接上代码
<template><div class="css-index"><el-inputv-model="searchText"placeholder="输入属性名搜索"clearableclass="search-box"/><div class="index-container"><div class="index-nav"><divv-for="letter in indexLetters":key="letter"class="nav-item"@click="scrollToLetter(letter)">{{ letter }}</div></div><div class="index-main"><div v-for="(group, letter) in filteredGroups":key="letter"class="index-group":ref="`group-${letter}`"><h3 class="group-title">{{ letter }}</h3><div class="property-list"><divv-for="prop in group":key="prop.name"class="property-item"@click="handleSelect(prop)"><span class="prop-name">{{ prop.name }}</span></div></div></div></div></div></div>
</template><script>
export default {name: 'CssIndexList',props: {// 接收处理后的列表数据cssProperties: {type: Object,required: true}},data() {return {searchText: ''}},computed: {// 转换数据结构processedProps() {return Object.keys(this.cssProperties).filter(name => {// 过滤无效属性return !name.startsWith('-webkit') && !name.startsWith('offset') && name !== 'length' && name !== 'parentRule'}).map(name => ({name,value: this.cssProperties[name]}))},// 按首字母分组groupedProps() {const groups = {}this.processedProps.forEach(prop => {const firstLetter = prop.name[0].toUpperCase()if (!groups[firstLetter]) {groups[firstLetter] = []}groups[firstLetter].push(prop)})return groups},// 过滤后的分组filteredGroups() {if (!this.searchText) return this.groupedPropsconst filtered = {}const searchKey = this.searchText.toLowerCase()Object.keys(this.groupedProps).forEach(letter => {const items = this.groupedProps[letter].filter(prop =>prop.name.toLowerCase().includes(searchKey))if (items.length > 0) {filtered[letter] = items}})return filtered},// 索引字母列表indexLetters() {return Object.keys(this.filteredGroups).sort()}},methods: {scrollToLetter(letter) {const el = this.$refs[`group-${letter}`]?.[0]el?.scrollIntoView({ behavior: 'smooth', block: 'start' })},handleSelect(prop) {this.$emit('select', prop.name)}}
}
</script><style scoped>
/* 保持原有样式不变 */
.css-index {width: 100%;height: 600px;display: flex;flex-direction: column;
}.search-box {margin-bottom: 15px;
}.index-container {flex: 1;display: flex;border: 1px solid #ebeef5;border-radius: 4px;overflow: hidden;
}.index-nav {width: 40px;background: #f5f7fa;padding: 10px 0;overflow-y: auto;
}.nav-item {padding: 4px;text-align: center;font-size: 12px;color: #606266;cursor: pointer;transition: all 0.3s;
}.nav-item:hover {color: #409eff;transform: scale(1.2);
}.index-main {flex: 1;overflow-y: auto;padding: 15px;
}.group-title {margin: 10px 0;color: #909399;font-size: 14px;padding-left: 8px;border-left: 3px solid #409eff;
}.property-list {display: grid;grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));gap: 10px;
}.property-item {padding: 8px 12px;border-radius: 4px;background: #f8f9fa;cursor: pointer;transition: all 0.2s;
}.property-item:hover {background: #ebf3ff;transform: translateX(4px);
}.prop-name {font-family: monospace;color: #303133;font-size: 13px;
}
</style>
使用
<indexed-list:css-properties="processedCssProperties"@select="handlePropSelect"/>mounted() {let cssList = window.getComputedStyle(document.body)for (const key of cssList) {this.processedCssProperties[key] = key}},handlePropSelect(prop) {console.log('选中属性:', prop)// 可以在这里处理属性复制等操作}