作用
用于过滤选择集(而非过滤数据),然后就可以对过滤之后的选择集进行相关操作了。
其他说明
- 如果通过d3在vue中动态创建dom元素,然后添加class,如果启用了scope,那么这个class默认情况下不会生效,要使其生效又要保持scope的话,必须使用
::v-deep
进行穿透 - 如果数据,选择集都没发生改变,d3并不会进行dom相关操作,这一定程度上也能让d3保持更好的性能(验证方式:对同一个按钮不停点击,观察html 的dom元素变化,你会发现html的dom节点并不会每次点击都会发生变化,只有条件改变,导致选择集变化时,dom节点才会改变)
效果演示
代码
<!--
TODO: 编写组件说明
@author pan
@date 2022-04-29
-->
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { select, selectAll } from 'd3-selection'
const myContainerRef = ref<HTMLDivElement>()
const dataArr = [
{ expense: 10, category: 'Retail' },
{ expense: 15, category: 'Gas' },
{ expense: 30, category: 'Retail' },
{ expense: 50, category: 'Dining' },
{ expense: 80, category: 'Gas' },
{ expense: 65, category: 'Retail' },
{ expense: 55, category: 'Gas' },
{ expense: 30, category: 'Dining' },
{ expense: 20, category: 'Retail' },
{ expense: 10, category: 'Dining' },
{ expense: 8, category: 'Gas' },
]
function render(data: any[], category?: string) {
const containerDom = myContainerRef.value as HTMLDivElement
select(containerDom)
.selectAll('div.h-bar') // <-B
.data(data)
.enter()
.append('div')
.attr('class', 'h-bar')
.append('span')
select(containerDom)
.selectAll('div.h-bar') // <-C
.data(data)
.exit()
.remove()
select(containerDom)
.selectAll('div.h-bar') // <-D
.data(data)
.attr('class', 'h-bar')
.style('width', function (d: any) {
return d.expense * 5 + 'px'
})
.select('span')
.text(function (d: any) {
return d.category
})
select(containerDom)
.selectAll('div.h-bar')
.filter(function (d: any, i) {
// <-E
console.log('category', category, d)
return d.category == category
})
.classed('selected', true)
}
onMounted(() => {
render(dataArr)
})
function doFilter(category?: string) {
render(dataArr, category)
}
</script>
<template>
<div class="myDiv">
<h3>表格</h3>
<button @click="doFilter('Retail')">Retail</button>
<button @click="doFilter('Gas')">Gas</button>
<button @click="doFilter('Dining')">Dining</button>
<button @click="doFilter()">Clear</button>
<div ref="myContainerRef"></div>
</div>
</template>
<style lang="scss" scoped>
.myDiv {
margin-left: 30px;
::v-deep(.h-bar) {
background-color: #42b8dd;
margin-bottom: 10px;
}
::v-deep(.selected) {
background-color: pink;
}
}
</style>