or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mddirectives.mdindex.mdplugin-installation.mdprogrammatic-api.md

components.mddocs/

0

# Lazy Components

1

2

Vue components for lazy loading content and images with full Vue 3 composition API support.

3

4

## Capabilities

5

6

### lazy-component

7

8

A wrapper component that lazily renders its content when it becomes visible in the viewport.

9

10

```typescript { .api }

11

/**

12

* Lazy component that renders content only when visible

13

*/

14

interface LazyComponentProps {

15

/** HTML tag to render as wrapper (default: 'div') */

16

tag?: string;

17

}

18

19

/**

20

* Events emitted by lazy-component

21

*/

22

interface LazyComponentEvents {

23

/** Emitted when component becomes visible and content is shown */

24

show: (visible: boolean) => void;

25

}

26

27

/**

28

* Slots available in lazy-component

29

*/

30

interface LazyComponentSlots {

31

/** Default slot content that will be lazily rendered */

32

default: () => VNode[];

33

}

34

```

35

36

**Usage Examples:**

37

38

```vue

39

<template>

40

<!-- Basic lazy component -->

41

<lazy-component @show="onComponentShow">

42

<img src="/heavy-image.jpg" alt="Heavy image">

43

<p>This content loads when visible</p>

44

</lazy-component>

45

46

<!-- Custom wrapper tag -->

47

<lazy-component tag="section" @show="onSectionShow">

48

<h2>Lazy Section</h2>

49

<video src="/large-video.mp4" controls></video>

50

</lazy-component>

51

52

<!-- In a list -->

53

<div class="image-gallery">

54

<lazy-component

55

v-for="(item, index) in galleryItems"

56

:key="item.id"

57

@show="() => onItemShow(index)"

58

>

59

<img :src="item.imageUrl" :alt="item.title">

60

<h3>{{ item.title }}</h3>

61

</lazy-component>

62

</div>

63

</template>

64

65

<script setup>

66

import { ref } from "vue";

67

68

const galleryItems = ref([

69

{ id: 1, imageUrl: "/gallery1.jpg", title: "Image 1" },

70

{ id: 2, imageUrl: "/gallery2.jpg", title: "Image 2" },

71

{ id: 3, imageUrl: "/gallery3.jpg", title: "Image 3" },

72

]);

73

74

const onComponentShow = (visible) => {

75

console.log("Component is now visible:", visible);

76

};

77

78

const onSectionShow = (visible) => {

79

console.log("Section became visible:", visible);

80

};

81

82

const onItemShow = (index) => {

83

console.log(`Gallery item ${index} is now visible`);

84

};

85

</script>

86

```

87

88

### lazy-image

89

90

A specialized component for lazy loading images with built-in state management and error handling.

91

92

```typescript { .api }

93

/**

94

* Lazy image component with built-in loading states

95

*/

96

interface LazyImageProps {

97

/** Image source URL or configuration object */

98

src: string | VueLazyloadImageOptions;

99

/** HTML tag to render (default: 'img') */

100

tag?: string;

101

}

102

103

/**

104

* Image options for lazy-image component

105

*/

106

interface VueLazyloadImageOptions {

107

/** Image source URL */

108

src: string;

109

/** Error fallback image URL */

110

error?: string;

111

/** Loading placeholder image URL */

112

loading?: string;

113

/** Maximum loading attempts */

114

attempt?: number;

115

}

116

117

/**

118

* Slots available in lazy-image component

119

*/

120

interface LazyImageSlots {

121

/** Optional slot content rendered alongside image */

122

default?: () => VNode[];

123

}

124

```

125

126

**Usage Examples:**

127

128

```vue

129

<template>

130

<!-- Basic lazy image -->

131

<lazy-image src="/photo.jpg" />

132

133

<!-- Image with configuration -->

134

<lazy-image :src="{

135

src: '/high-res-photo.jpg',

136

loading: '/loading-placeholder.png',

137

error: '/error-fallback.png',

138

attempt: 3

139

}" />

140

141

<!-- Custom wrapper tag -->

142

<lazy-image

143

tag="figure"

144

:src="imageConfig"

145

>

146

<figcaption>Image caption content</figcaption>

147

</lazy-image>

148

149

<!-- Dynamic image source -->

150

<lazy-image

151

:src="computedImageSrc"

152

@load="onImageLoaded"

153

@error="onImageError"

154

/>

155

</template>

156

157

<script setup>

158

import { computed, ref } from "vue";

159

160

const imageConfig = ref({

161

src: "/portrait.jpg",

162

loading: "/skeleton-loader.svg",

163

error: "/broken-image.svg",

164

attempt: 5,

165

});

166

167

const imageQuality = ref("medium");

168

const imageName = ref("landscape");

169

170

const computedImageSrc = computed(() => ({

171

src: `/images/${imageName.value}-${imageQuality.value}.jpg`,

172

loading: "/placeholders/image-loading.svg",

173

error: "/placeholders/image-error.svg",

174

}));

175

176

const onImageLoaded = () => {

177

console.log("Lazy image successfully loaded");

178

};

179

180

const onImageError = () => {

181

console.error("Failed to load lazy image");

182

};

183

</script>

184

```

185

186

### Component Integration Patterns

187

188

Advanced usage patterns for integrating lazy components with other Vue features.

189

190

**With Vue Router:**

191

192

```vue

193

<template>

194

<router-view v-slot="{ Component }">

195

<lazy-component @show="onRouteComponentShow">

196

<component :is="Component" />

197

</lazy-component>

198

</router-view>

199

</template>

200

201

<script setup>

202

import { useRoute } from "vue-router";

203

204

const route = useRoute();

205

206

const onRouteComponentShow = () => {

207

console.log("Route component visible:", route.path);

208

};

209

</script>

210

```

211

212

**With Suspense:**

213

214

```vue

215

<template>

216

<Suspense>

217

<template #default>

218

<lazy-component @show="onAsyncComponentShow">

219

<AsyncComponent />

220

</lazy-component>

221

</template>

222

<template #fallback>

223

<div class="loading-placeholder">Loading async component...</div>

224

</template>

225

</Suspense>

226

</template>

227

228

<script setup>

229

import { defineAsyncComponent } from "vue";

230

231

const AsyncComponent = defineAsyncComponent(() => import("./HeavyComponent.vue"));

232

233

const onAsyncComponentShow = () => {

234

console.log("Async component is now visible");

235

};

236

</script>

237

```

238

239

**With Teleport:**

240

241

```vue

242

<template>

243

<lazy-component @show="onModalContentShow">

244

<Teleport to="#modal-container">

245

<div class="modal-content">

246

<lazy-image :src="modalImageSrc" />

247

</div>

248

</Teleport>

249

</lazy-component>

250

</template>

251

252

<script setup>

253

const modalImageSrc = ref("/modal-background.jpg");

254

255

const onModalContentShow = () => {

256

console.log("Modal content is visible");

257

};

258

</script>

259

```

260

261

### Performance Optimization

262

263

Optimizing lazy component performance for large lists and complex layouts.

264

265

**Virtual Scrolling Integration:**

266

267

```vue

268

<template>

269

<div class="virtual-list" ref="scrollContainer">

270

<lazy-component

271

v-for="item in visibleItems"

272

:key="item.id"

273

@show="() => trackItemView(item.id)"

274

>

275

<ItemComponent :item="item" />

276

</lazy-component>

277

</div>

278

</template>

279

280

<script setup>

281

import { ref, computed } from "vue";

282

283

const scrollContainer = ref();

284

const allItems = ref([/* large array of items */]);

285

286

// Only render items in viewport + buffer

287

const visibleItems = computed(() => {

288

// Implementation for virtual scrolling logic

289

return allItems.value.slice(startIndex.value, endIndex.value);

290

});

291

292

const trackItemView = (itemId) => {

293

// Analytics tracking when item becomes visible

294

console.log("Item viewed:", itemId);

295

};

296

</script>

297

```

298

299

**Intersection Observer Configuration:**

300

301

```vue

302

<template>

303

<lazy-component

304

@show="onHighPriorityShow"

305

data-lazy-priority="high"

306

>

307

<CriticalContent />

308

</lazy-component>

309

310

<lazy-component

311

@show="onLowPriorityShow"

312

data-lazy-priority="low"

313

>

314

<OptionalContent />

315

</lazy-component>

316

</template>

317

318

<script setup>

319

// Components automatically inherit observer settings from plugin config

320

// Can be customized via global configuration during plugin installation

321

322

const onHighPriorityShow = () => {

323

// Handle high priority content visibility

324

};

325

326

const onLowPriorityShow = () => {

327

// Handle low priority content visibility

328

};

329

</script>

330

```

331

332

### Component State Management

333

334

Managing component states and lifecycle hooks.

335

336

```vue

337

<template>

338

<lazy-component @show="handleComponentShow">

339

<div class="content-wrapper">

340

<lazy-image

341

:src="imageSource"

342

@loading="onImageLoading"

343

@loaded="onImageLoaded"

344

@error="onImageError"

345

/>

346

<div class="content-text">

347

{{ contentText }}

348

</div>

349

</div>

350

</lazy-component>

351

</template>

352

353

<script setup>

354

import { ref, nextTick } from "vue";

355

356

const imageSource = ref("/initial-image.jpg");

357

const contentText = ref("Initial content");

358

const isComponentVisible = ref(false);

359

360

const handleComponentShow = async (visible) => {

361

isComponentVisible.value = visible;

362

363

if (visible) {

364

// Load additional resources when component becomes visible

365

await loadAdditionalResources();

366

}

367

};

368

369

const onImageLoading = () => {

370

console.log("Image started loading");

371

};

372

373

const onImageLoaded = () => {

374

console.log("Image finished loading");

375

// Trigger any post-load animations or updates

376

nextTick(() => {

377

// DOM updates after image load

378

});

379

};

380

381

const onImageError = () => {

382

console.error("Image failed to load");

383

// Fallback behavior

384

imageSource.value = "/fallback-image.jpg";

385

};

386

387

const loadAdditionalResources = async () => {

388

// Fetch additional data when component is visible

389

const response = await fetch("/api/additional-content");

390

const data = await response.json();

391

contentText.value = data.text;

392

};

393

</script>

394

```