Vue3组合式API中Template Refs的TypeScript空值处理最佳实践
问题
我正在开发一个使用Vue3组合式API与TypeScript的项目,第一步是通过HTMLCanvasElement渲染足球场。为了在<script>标签中访问其属性,我为它设置了Template Ref,并按照Vue文档声明为const canvas = ref<HTMLCanvasElement | null>(null)。但后续大量代码因canvas可能为null出现TypeScript报错。
我的疑问是:应当在所有canvas.value后添加可选链?(如canvas.value?.width),还是在每个方法开头添加if判断canvas.value不为null?
以下是我的TS代码,错误出现在render方法的前3行:
const canvas = ref<HTMLCanvasElement | null>(null); function fitToContainer(canvas : HTMLCanvasElement){ canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; } function render(ctx: CanvasRenderingContext2D) { // Adjusting the canvas to the right dimenstions fitToContainer(canvas.value); const canvasWidth = canvas.value.width; const canvasHeight = canvas.value.height; // ---------------- FILL FIELD WITH COLOR ---------------- ctx.fillStyle = "#3bad59"; ctx.clearRect(0, 0, canvasWidth, canvasHeight); ctx.fillRect(0, 0, canvasWidth, canvasHeight); // ---------------- DRAW LINES ---------------- }
解决方案
两种方式的对比
- 可选链
?.:代码写法更简洁,但存在隐患——如果canvas.value为null,canvasWidth、canvasHeight会变成undefined,后续依赖这些变量的运行时代码大概率会抛出Cannot read properties of undefined错误,而且TypeScript仍会提示变量可能为undefined,需要额外处理。 - 开头加if判断:能一次性排除null场景,TypeScript会自动收窄
canvas.value的类型为HTMLCanvasElement,后续代码无需再重复处理null情况,逻辑更安全,也能减少类型提示的困扰。
优化后的代码
推荐在render方法开头先判断canvas.value是否存在,不存在直接终止执行,避免后续报错:
const canvas = ref<HTMLCanvasElement | null>(null); function fitToContainer(canvas : HTMLCanvasElement){ canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; } function render(ctx: CanvasRenderingContext2D) { // 先判断canvas是否挂载完成,未完成直接终止 if (!canvas.value) return; // Adjusting the canvas to the right dimenstions fitToContainer(canvas.value); const canvasWidth = canvas.value.width; const canvasHeight = canvas.value.height; // ---------------- FILL FIELD WITH COLOR ---------------- ctx.fillStyle = "#3bad59"; ctx.clearRect(0, 0, canvasWidth, canvasHeight); ctx.fillRect(0, 0, canvasWidth, canvasHeight); // ---------------- DRAW LINES ---------------- }
补充说明:如果render是在Vue的onMounted等生命周期钩子中调用,理论上canvas.value已经挂载完成不为null,但TypeScript无法识别这一上下文,所以仍需手动加判断;若你能100%确认canvas.value不会为null,也可以用非空断言!(如canvas.value!),但这种写法风险较高,仅在场景明确时使用。
内容的提问来源于stack exchange,提问作者Alexandru Lolea
相关产品推荐
相关产品推荐

