Code Block
Cách sử dụng
1. Chuẩn bị CSS
Sử dụng useDynamicStyle composable để import CSS động. Cách này đảm bảo CSS chỉ được load khi component mount và tự động cleanup khi unmount, tránh ảnh hưởng đến các trang khác:
<script lang="ts" setup>
const { waitReady: waitReadyStyleCodeBlock, markReady: markStyleReady } =
useReadyBarrier();
useDynamicStyle(
() => import("~/assets/css/code-block/index.css?inline"),
() => {
markStyleReady();
},
);
</script>
2. Tạo textarea
<textarea
ref="textarea"
class="prism-live line-numbers language-markdown"
></textarea>
3. Khởi tạo PrismLive
<script lang="ts" setup>
import PrismLive from "@nguyentantaitcag2000/lazycodet/dist/prism-live";
const textarea = ref<HTMLTextAreaElement>();
onMounted(async () => {
// Chờ CSS load xong trước khi khởi tạo editor
await waitReadyStyleCodeBlock();
// Khởi tạo PrismLive
const prismLive = PrismLive.create(textarea.value!, {
callbackEvents: {
onKeyUp: (event: KeyboardEvent, textarea: HTMLTextAreaElement) => {
// Xử lý khi gõ phím
},
onKeyDown: (event: KeyboardEvent, textarea: HTMLTextAreaElement) => {
// X xử lý khi nhấn phím
},
},
});
});
</script>
Cập nhật content thủ công (Programmatic Content Update)
Khi nội dung của textarea được cập nhật programmatically (ví dụ: nhận data từ API), PrismLive không tự động re-highlight. Bạn cần gọi update() trên PrismLive instance để cập nhật syntax highlighting.
Cách thực hiện:
<script lang="ts" setup>
import { ref, watch, nextTick, onMounted } from "vue";
import PrismLive from "@nguyentantaitcag2000/lazycodet/dist/prism-live";
const { waitReady: waitReadyStyleCodeBlock, markReady: markStyleReady } =
useReadyBarrier();
useDynamicStyle(
() => import("~/assets/css/code-block/index.css?inline"),
() => {
markStyleReady();
},
);
const textarea = ref<HTMLTextAreaElement>();
const content = ref("");
let prismLive: any = null;
// Watch for content changes and update PrismLive highlight
watch(content, () => {
if (prismLive) {
nextTick(() => {
prismLive.update();
});
}
});
// Khởi tạo PrismLive
onMounted(async () => {
await waitReadyStyleCodeBlock();
if (textarea.value) {
prismLive = PrismLive.create(textarea.value, {
callbackEvents: {
onKeyUp: (_event: KeyboardEvent, textarea: HTMLTextAreaElement) => {
content.value = textarea.value;
},
},
});
}
});
// Hàm cập nhật content từ API
async function fetchAndSetContent() {
const response = await $fetch("/api/some-endpoint");
content.value = response.data; // Watch sẽ tự động gọi prismLive.update()
}
</script>
Cho phép xuống dòng
Mặc định, code-block sẽ không xuống dòng khi nội dung dài. Để cho phép xuống dòng, thêm class .prism-wrap vào thẻ cha chứa code-block:
<div class="prism-wrap">
<textarea
ref="textarea"
class="prism-live line-numbers language-markdown"
></textarea>
</div>
Lưu ý khi sử dụng .line-numbers
Khi sử dụng .line-numbers, layout phải được cố định ngay từ đầu. Nếu code-block nằm trong wrapper có dạng flex và các phần tử khác được thêm vào sau khi load DOM, chiều rộng của code-block sẽ bị thu hẹp. Khi đó code-block không nhận biết được sự kiện resize nên không vẽ lại số dòng, dẫn đến hiển thị sai.