ESLint 规则
Qwik 自带一套 ESLint 规则,帮助开发者编写更好的代码。
✅ 警告 在 'recommended' 规则集中
✅ 错误 在 'recommended' 规则集中
🔔 警告 在 'strict' 规则集中
🔔 错误 在 'strict' 规则集中
可能的问题
这些规则可用。
use-method-usage
检测 use 钩子的无效使用。✅
🔔
valid-lexical-scope
使用 tsc 类型检查器检测在美元 ($) 范围中捕获不可序列化数据的行为。✅
🔔
loader-location
检测 loader$ 的声明位置。✅
🔔
no-react-props
禁止使用 React 特定的 className
/htmlFor
属性。✅
🔔
prefer-classlist
强制使用 classlist 属性而不是导入 classnames 助手。classlist 属性接受一个对象 { [class: string]: boolean }
,就像 classnames 一样。✅
🔔
jsx-no-script-url
禁止使用 javascript: URL。✅
🔔
jsx-key
禁止在迭代器/集合字面量中缺少 key
属性✅
🔔
unused-server
检测未使用的 server$() 函数。✅
🔔
jsx-img
出于性能原因,始终为 <img> 元素提供 width 和 height 属性,这将有助于防止布局偏移。✅
🔔
jsx-a
为了获得完美的 SEO 分数,始终为 <a> 元素提供 href 属性。✅
🔔
no-use-visible-task
检测 useVisibleTask$() 函数。✅
🔔
详情
use-method-usage
检测 use 钩子的无效使用。useWrongFunction
此规则的正确代码示例
export const Counter = component$(() => {
const count = useSignal(0);
});
export const useCounter = () => {
const count = useSignal(0);
return count;
};
此规则的错误代码示例
export const Counter = (() => {
const count = useSignal(0);
});
use*
方法只能在 component$
函数中或 use*
钩子(例如 useCounter
)内使用。
valid-lexical-scope
使用 tsc 类型检查器检测在美元 ($) 范围中捕获不可序列化数据的行为。referencesOutside
此规则的正确代码示例
import { component$, useTask$, $ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const print = $((msg: string) => {
console.log(msg);
});
useTask$(() => {
print("Hello World");
});
return <h1>Hello</h1>;
});
此规则的错误代码示例
import { component$, useTask$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const print = (msg: string) => {
console.log(msg);
};
useTask$(() => {
print("Hello World");
});
return <h1>Hello</h1>;
});
由于表达式不可序列化,因此必须用 $( ... )
包裹它们,以便优化器可以将代码拆分为小块。
invalidJsxDollar
此规则的正确代码示例
import { component$, $ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const click = $(() => console.log());
return (
<button onClick$={click}>log it</button>
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const click = () => console.log();
return (
<button onClick$={click}>log it</button>
);
});
事件处理程序必须用 ${ ... }
包裹。
mutableIdentifier
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const person = { name: 'Bob' };
return (
<button onClick$={() => {
person.name = 'Alice';
}}>
{person.name}
</button>
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
let personName = 'Bob';
return (
<button onClick$={() => {
personName = 'Alice';
}}>
{personName}
</button>
);
});
不允许修改简单值。请改用对象,并修改其属性之一。
loader-location
检测 loader$ 的声明位置。invalidLoaderLocation
此规则的正确代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
此规则的错误代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
这不是路由加载器的有效位置。它只能在 src/routes
文件夹内,在 layout.tsx
或 index.tsx
文件中使用。
missingExport
此规则的正确代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
此规则的错误代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
路由加载器函数必须导出。
wrongName
此规则的正确代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
此规则的错误代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const getProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
路由加载器函数名必须以 use
开头。
recommendedValue
此规则的正确代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
此规则的错误代码示例
import { routeLoader$ } from '@builder.io/qwik-city';
async function fetcher() {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
}
export const useProductDetails = routeLoader$(fetcher);
建议内联箭头函数。这将有助于优化器确保没有服务器代码泄漏到客户端构建中。
no-react-props
禁止使用 React 特定的className
/htmlFor
属性。prefer
此规则的正确代码示例
<MyReactComponent class="foo" for="#password" />;
此规则的错误代码示例
<MyReactComponent className="foo" htmlFor="#password" />;
优先使用 class
和 for
属性而不是 className
和 htmlFor
。
prefer-classlist
强制使用 classlist 属性而不是导入 classnames 助手。classlist 属性接受一个对象{ [class: string]: boolean }
,就像 classnames 一样。preferClasslist
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
import styles from './MyComponent.module.css';
export default component$((props) => {
// Array syntax example
return <div class={[
styles.container,
'p-8',
props.isHighAttention ? 'text-green-500' : 'text-slate-500',
{ active: true}
]}>Hello world</div>;
// Object syntax example
return <div class={{
'text-green-500': props.isHighAttention,
'p-4': true
}}>Hello world</div>;
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
import classnames from 'classnames';
import styles from './MyComponent.module.css';
export default component$((props) => {
return <div class={classnames(
styles.container,
'p-8',
{
'text-green-500' : props.isHighAttention,
'text-slate-500' : !props.isHighAttention,
},
{ active: true}
)}>Hello world</div>;
});
应使用 class 属性而不是任何第三方库来根据对象有效地设置类。
jsx-no-script-url
禁止使用 javascript: URL。noJSURL
此规则的正确代码示例
<button onClick$={() => alert('open the door please')>ring</button>
此规则的错误代码示例
<button onClick$="javascript:alert('open the door please')">ring</button>
jsx-key
禁止在迭代器/集合字面量中缺少key
属性missingIterKey
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
<ul>
{Object.keys(person).map((color) => (
<li key={`person-${key}`}>{person[key]}</li>
)}
</ul>
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
<ul>
{Object.keys(person).map((color) => (
<li>{person[key]}</li>
)}
</ul>
);
});
迭代器中的元素缺少 key
属性。
missingIterKeyUsePrag
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
import Card from './Card';
import Summary from './Summary';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
{Object.keys(person).map((color) => (
<Fragment key={`person-${key}`}>
<Card value={person[key]} />
<Summary value={person[key]} />
</Fragment>
)}
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
import Card from './Card';
import Summary from './Summary';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
{Object.keys(person).map((color) => (
< key={`person-${key}`}>
<Card value={person[key]} />
<Summary value={person[key]} />
</>
)}
);
});
迭代器中的元素缺少 key
属性。key 属性可以提高渲染性能。简写片段语法不支持提供 key。请改用 <Fragment>
missingArrayKey
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key={`color-${color}`}>{color}</li>
)}
</ul>
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li>{color}</li>
)}
</ul>
);
});
数组中的元素缺少 key
属性。key 属性可以提高渲染性能。
missingArrayKeyUsePrag
此规则的正确代码示例
import { component$, Fragment } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
{colors.map((color) => (
<Fragment key={`color-${color}`}>
<h2>{color}</h2>
<p>The color "${color}" is a great color.</p>
</Fragment>
)}
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
{colors.map((color) => (
< key={`color-${color}`}>
<h2>{color}</h2>
<p>The color "${color}" is a great color.</p>
</>
)}
);
});
数组中的元素缺少 key
属性。key 属性可以提高渲染性能。简写片段语法不支持提供 key。请改用 <Fragment>
nonUniqueKeys
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key={`color-${color}`}>{color}</li>
)}
</ul>
);
});
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key="not-a-good-idea">{color}</li>
)}
</ul>
);
});
key
属性必须是唯一的。
unused-server
检测未使用的 server$() 函数。unusedServer
此规则的正确代码示例
import { component$ } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
const serverGreeter = server$((firstName: string, lastName: string) => {
const greeting = `Hello ${firstName} ${lastName}`;
return greeting;
});
export default component$(() => (
<button
onClick$={async () => {
const greeting = await serverGreeter('John', 'Doe');
alert(greeting);
}}
>
greet
</button>
);
);
此规则的错误代码示例
import { component$ } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
const serverGreeter = server$((firstName: string, lastName: string) => {
const greeting = `Hello ${firstName} ${lastName}`;
return greeting;
});
export default component$(() => (
<button
onClick$={async () => {
const greeting = 'not using the server$ function';
alert(greeting);
}}
>
greet
</button>
);
);
声明了一个 server$
函数,但从未使用过。
jsx-img
出于性能原因,始终为 <img> 元素提供 width 和 height 属性,这将有助于防止布局偏移。noLocalSrc
此规则的正确代码示例
import Image from '~/media/image.png';
<Image />
此规则的错误代码示例
<img src="/image.png">
从 public 目录提供图像既没有优化,也没有缓存。请使用 ESM 导入图像。
noWidthHeight
此规则的正确代码示例
<img width="200" height="600" src="/static/images/portrait-01.webp">
此规则的错误代码示例
<img src="/static/images/portrait-01.webp">
出于性能原因,始终为 <img>
元素提供 width 和 height 属性,这将有助于防止布局偏移。