66 <div
77 ref =" viewer"
88 class =" vue-diff-viewer"
9- :style =" { height: viewerHeight ? viewerHeight + 'px' : undefined }"
9+ :style =" { height: scrollOptions ? scrollOptions.height + 'px' : undefined }"
1010 >
1111 <div
1212 class =" vue-diff-viewer-inner"
13- :style =" { minHeight: innerMinHeight ? innerMinHeight + 'px' : undefined }"
13+ :style =" { minHeight: minHeight ? minHeight + 'px' : undefined }"
1414 >
1515 <Line
16+ v-for =" (data, index) in visible"
1617 :key =" index"
17- v-for =" (data, index) in visibleData"
18- :index =" index"
1918 :mode =" mode"
2019 :language =" language"
21- :data =" data"
22- :virtualScroll =" virtualScroll"
23- @set-line-height =" setLineHeight"
20+ :meta =" meta[data.index]"
21+ :render =" render[data.index]"
22+ :virtualScroll =" scrollOptions"
23+ @setLineHeight =" setLineHeight"
2424 />
2525 </div >
2626 </div >
2727 </div >
2828</template >
2929
3030<script lang="ts">
31- import { defineComponent , PropType , ref , watch , onMounted , onBeforeUnmount , computed , readonly , toRaw } from ' vue'
32- import throttle from ' lodash-es/throttle'
33- import { renderLines , renderWords } from ' ./utils'
31+ import {
32+ computed ,
33+ defineComponent ,
34+ onMounted ,
35+ ref ,
36+ watch
37+ } from ' vue'
38+ import debounce from ' lodash-es/debounce'
39+ import { useVirtualScroll } from ' ./hooks'
40+ import { renderLines } from ' ./utils'
3441import Line from ' ./Line.vue'
3542
36- import type { Mode , Theme , Lines } from ' ./utils'
37-
38- interface VirtualScroll {
39- height? : number ;
40- lineMinHeight? : number ;
41- }
42-
43- interface Data {
44- key: number ;
45- render: Lines ;
46- top? : number ;
47- height? : number ;
48- }
43+ import type { PropType } from ' vue'
44+ import type { Meta , VirtualScroll , Mode , Theme , Lines } from ' ./types'
4945
5046export default defineComponent ({
5147 components: {
@@ -72,101 +68,71 @@ export default defineComponent({
7268 type: String ,
7369 default: ' '
7470 },
71+ inputDelay: {
72+ type: Number ,
73+ default: 0
74+ },
7575 virtualScroll: {
76- type: false || Object as PropType <VirtualScroll >,
76+ type: [ Boolean , Object ] as PropType <boolean | VirtualScroll >,
7777 default: false
7878 }
7979 },
8080 setup (props ) {
8181 const viewer = ref <null | HTMLElement >(null )
82- const source = ref <Array <Data >>([])
83- const visibleData = ref <Array <Data >>([])
84- const heightList = ref <Array <number >>([])
85-
86- const viewerHeight = computed (() => {
87- if (! props .virtualScroll ) return false
88- return props .virtualScroll .height || 500
89- })
90-
91- const innerMinHeight = computed (() => {
92- if (! props .virtualScroll ) return false
93- return heightList .value .reduce ((acc , curr ) => acc + curr , 0 )
82+ const meta = ref <Array <Meta >>([])
83+ const render = ref <Array <Lines >>([])
84+ const visible = computed (() => meta .value .filter (item => item .visible ))
85+ const { minHeight, scrollOptions, setMeta } = useVirtualScroll ({
86+ meta ,
87+ viewer ,
88+ virtualScroll: props .virtualScroll ,
89+ render
9490 })
9591
96- const getVisibleData = () => {
97- if (! viewer .value || ! viewerHeight .value ) return []
98-
99- const result: Data [] = []
100- const start = viewer .value .scrollTop - viewerHeight .value
101- const end = viewer .value .scrollTop + viewerHeight .value * 2
102-
103- heightList .value .reduce ((acc , curr , index : number ) => {
104- if (acc >= start && acc <= end ) {
105- result .push ({
106- key: index ,
107- render: source .value [index ].render ,
108- top: acc ,
109- height: 24
110- })
92+ const setData = () => {
93+ render .value = renderLines (props .mode , props .prev , props .current )
94+ meta .value .splice (render .value .length )
95+ render .value .map ((v , index : number ) => {
96+ const item = meta .value [index ]
97+ meta .value [index ] = {
98+ index ,
99+ visible: item ?.visible || ! props .virtualScroll ,
100+ top: item ?.top || undefined ,
101+ height: item ?.height || 24
111102 }
112-
113- return acc + curr
114- }, 0 )
115-
116- return result
117- }
118-
119- const handleScroll = () => {
120- visibleData .value = getVisibleData ()
121- }
122-
123- const setLineHeight = (index : number , height : number ) => {
124- const item = source .value .find (item => item .key === index )
125- if (item ) {
126- item .height = height
127- }
103+ })
104+ setMeta ()
128105 }
129106
130107 onMounted (() => {
131- if (! viewer .value ) return
132- viewer .value .addEventListener (' scroll' , throttle (handleScroll , 500 ))
133-
134- watch ([
135- () => props .mode ,
136- () => props .prev ,
137- () => props .current
138- ], () => {
139- source .value = renderLines (props .mode , props .prev , props .current ).map ((render , index ) => {
140- return {
141- key: index ,
142- render ,
143- height: 24
144- }
145- })
146-
147- if (! props .virtualScroll ) {
148- if (source .value .length > 500 ) {
149- console .warn (' If there are many lines, please use virtualScroll property.' )
150- }
151-
152- visibleData .value = source .value
153- } else {
154- visibleData .value = getVisibleData ()
108+ watch (
109+ [
110+ () => props .mode ,
111+ () => props .prev ,
112+ () => props .current
113+ ],
114+ debounce (setData , props .inputDelay ),
115+ {
116+ immediate: true ,
117+ deep: true
155118 }
156- }, { immediate: true } )
119+ )
157120 })
158121
159- onBeforeUnmount (() => {
160- if (! viewer .value ) return
161- viewer .value .removeEventListener (' scroll' , throttle (handleScroll , 500 ))
162- })
122+ const setLineHeight = (index : number , height : number ) => {
123+ if (meta .value [index ]) {
124+ meta .value [index ].height = height
125+ }
126+ }
163127
164128 return {
165- visibleData ,
129+ meta ,
130+ minHeight ,
131+ render ,
132+ scrollOptions ,
133+ setLineHeight ,
166134 viewer ,
167- viewerHeight ,
168- innerMinHeight ,
169- setLineHeight
135+ visible
170136 }
171137 }
172138})
0 commit comments