点击上方“开发者技术前线”,选择“星标”

13:21 在看 真爱

640?wx_fmt=jpeg

作者 | Mark Volkmann译者 | 王强  编辑 | 张之栋、王文婧
近年来,Web 框架层出不穷,作为主流 Web 框架之一的 Svelte,有着独特的优势。它不仅可以构建完整的 Web 应用程序,还可以创建自定义元素,并在其他框架实现的已有 Web 应用程序中使用。本文将对 Svelte 进行详细的介绍,并带领读者了解使用 Svelte 从头开始构建 Web 应用程序所需的基础知识。
Svelte 是什么?

Svelte 是 React、Vue 和 Angular 等 Web 框架的替代方案。与其同类产品一样,Svelte 可用于构建完整的 Web 应用程序。它还能用来创建自定义元素,这些自定义元素可以在使用其他框架实现的已有 Web 应用程序中使用。

Svelte 由 Rich Harris 开发,Rich Harris 曾在《卫报》工作,目前任职于《纽约时报》。Harris 先前创建的 Ractive Web 框架被《卫报》采用,并成为 Vue 的部分功能的灵感来源。Harris 还创建了 Rollup 模块打包器,它是 Webpack 和 Parcel 的替代品。

Svelte 尚未得到应有的重视。人们提到它时往往更关注它生成打包代码的能力,它打包出来的代码明显比竞争对手更小。但除此之外 Svelte 还简化了许多工作,包括定义组件、管理组件状态、管理应用程序状态以及添加动画等。

本文对 Svelte 进行了详尽的介绍,并提供了使用它从头开始构建 Web 应用程序所需的基础知识。

为什么要用 Svelte?

与其他 Web 框架创建的应用程序相比,Svelte 应用程序的包体积较小。它将应用程序代码编译到一个只包含少量框架代码的优化过的 JavaScript 文件来做到了这一点。

Svelte 是用 TypeScript 实现的 Web 应用程序编译器。它不是运行时库。例如,稍后介绍的 Todo 应用程序的包体积只有等效 React 应用程序的 13%。这两款应用程序的链接如下:

https://github.com/mvolkmann/svelte-todo

https://github.com/mvolkmann/react-todo

一项调查统计了现实世界中 Web 应用使用多种 Web 框架构建的相关数据。统计显示,使用一些流行框架的应用经过 gzip 压缩后的大小(KB)分别为:
  • Angular + ngrx:134
  • React + Redux:193
  • Vue:41.8
  • Svelte:9.7

调查报告:

https://www.freecodecamp.org/news/a-realworld-comparison-of-front-end-frameworks-with-benchmarks-2019-update-4be0d3c78075/

某些 Web 框架(包括 React 和 Vue)使用虚拟 DOM 来优化渲染更改。重新渲染组件时,框架会在内存中构建 DOM 的新版本,然后将其与以前的版本做对比,不一样的部分才会被应用到实际的 DOM 上。

尽管这比更新实际 DOM 中的所有内容要快,但构建虚拟 DOM 并将其与前一个 DOM 进行比较是需要花时间的。

Svelte 无需使用虚拟 DOM 就可以提供反应性。为了做到这一点,它会跟踪影响各个组件渲染的顶级组件变量的更改,并仅在检测到更改时才重新渲染 DOM 的这些部分。这样就能获得良好的性能表现。

Svelte 大大简化了组件和应用程序状态管理。相关功能包括上下文、存储和模块上下文,稍后将逐一详细介绍。

Svelte 为可访问性问题提供了运行时警告。例如,没有 alt 属性的<img>元素会被标记出来。Svelte 当前不支持 TypeScript,但正在推进相关工作。Svelte Native 支持开发移动应用程序。它基于 NativeScript。

Svelte 会消失吗?

有人说一旦应用程序构建完毕,Svelte 就会消失。

Svelte 库主要由 node_modules/svelte 目录中的.js 文件定义。主要函数在 internal.js 中定义,目前大约有 1400 行代码。

其他库文件则针对特定功能,具体包括:
  • easing.js
  • motion.js
  • register.js
  • store.js
  • transition.js

输入 npm run build 会在 public 目录中生成文件,包括 bundle.js。应用程序使用的 Svelte 库函数将复制到 bundle.js 的顶部。后文展示的 Todo 应用程序中,这里大约是 500 行代码。

因此 Svelte 库代码不会消失,只是它与其他 Web 框架相比体积很小。

重要资源
下面是学习 Svelte 时需要查看的重要资源列表:
  • 重新思考反应性:https://svelte.dev/blog/svelte-3-rethinking-reactivity

这是 Rich Harris 在 You Gotta Love Frontend(YGLF)Code Camp 2019 上的演讲。它解释了 Svelte 3 背后的动力,并提供了一些简要介绍。
  • Svelte 主页:https://svelte.dev
  • Svelte 教程:https://svelte.dev/tutorial
  • Svelte API:https://svelte.dev/docs
  • Svelte 示例:https://svelte.dev/examples
  • 在线 Svelte REPL:https://svelte.dev/repl

想要尝试编写少量 Svelte 代码的话这个网站很有用。它还可以显示生成的代码并保存代码,以供分享和提交问题。
  • Svelte 博客:https://svelte.dev/blog
  • Discord 聊天室:https://discordapp.com/invite/yy75DKs
  • Svelte GitHub 存储库:https://github.com/sveltejs/svelte

入  门 
下面我们来一步步创建并运行一个 Svelte 应用程序。
  1. 从 https://nodejs.org 安装 Node.js。

这将安装 node、npm 和 npx 命令。
  1. npx degit sveltejs/template app-name

Rich Harris 创建了 degit 工具来简化项目框架。它会下载一个 git 仓库,默认为 master 分支。本例中“sveltejs”是用户名,“template”是存储库。第二个参数是要创建的目录名称。
  1. cd app-name
  2. npm install
  3. npm run dev

这将启动本地 HTTP 服务器并提供实时重载,这与 npm run start 是不一样的,后者忽略了实时重载。语法错误是在运行该命令的窗口中,而不是在浏览器中报告的。这是因为如果出现了错误,Svelte 不会生成该应用程序的新版本。
  1. 浏览localhost:5000

这一步会输出紫色的“Hello world!”。

现在你可以开始修改应用程序了。

初探package.json文件会发现两件事。首先是 Svelte 默认使用 Rollup 来打包模块。需要的话,可以将其更改为使用 Webpack 或 Parcel。其次是 Svelte 应用程序没有必需的运行时依赖项,只有 devDependencies。

最重要的起始文件包括:
public/index.html
src/main.js
src/App.svelte
这些文件使用 tab 缩进,但需要的话可以将 tab 替换为空格。
  1. 文件 public/index.html包含以下内容:

<!DOCTYPE html>
<html><head><meta charset="utf8" /><meta name="viewport" content="width=device-width" /><title>Svelte app</title><link rel="icon" type="image/png" href="favicon.png" /><link rel="stylesheet" href="global.css" /><link rel="stylesheet" href="bundle.css" /></head><body><script src="bundle.js"></script></body>
</html>
请注意这里提取了两个 CSS 文件和一个 JavaScript 文件。
  • global.css包含可以影响任何组件的 CSS。
  • bundle.css由每个组件中的 CSS 生成。
  • bundle.js是由每个组件中的 JavaScript 和 HTML,以及应用程序中其他所有的 JavaScript 生成的。

  1. 文件src/main.js包含以下内容:

import App from './App.svelte';const app = new App({target: document.body,props: {name: 'world'}
});export default app;
这里会渲染 App 组件。target 属性指定应在何处渲染组件。对于大多数应用程序来说,这就是文档的主体。name prop 会传递给 App 组件。通常来说最顶层的组件不需要 props,此处的 props 属性可以删除。
  1. 文件src/App.svelte包含以下内容:

<script>export let name;
</script><style>h1 {color: purple;}
</style><h1> Hello {name}! </h1>

可以在使用该组件的文件中将导出的变量设置为 props。

大括号用于输出 JavaScript 表达式的值。这里称为 插值。稍后我们将看到,大括号也用于动态属性值。

定义组件 
流行的 Web 框架使用多种 JavaScript 容器来定义组件。
  • Angular 使用类。
  • React 使用函数或类。
  • Vue 使用对象字面量。

Svelte 不使用任何 JavaScript 容器。

Svelte 组件由包含 JavaScript 代码、CSS 和 HTML 的.svelte 文件定义。它们组合在一起形成组件定义,该定义将自动成为默认导出。

.svelte 文件可以在 src 目录下的任何位置。它们包含以下三部分,这三部分都是可选的。

<script>// 确定范围的 JavaScript 在这里。
</script><style>/* 确定范围的 CSS 规则在这里。*/
</style><!-- 要渲染的 HTML 在这里。-->

请注意,每个部分都可以使用不同的注释语法。

组件名称

Svelte 组件定义未指定组件名称。其他框架中组件名称是在源文件中由类名称、函数名称或属性值提供的,这里不是这样,导入.svelte 文件时组件名称会被关联,并且必须以大写字母开头。小写名称保留给预定义元素,例如 HTML 和 SVG 提供的元素。

// 有些令人困惑
import AnyNameIWant from './some-name.svelte';// 较清晰的写法
import SameName from './SameName.svelte';
共享数据

在 Svelte 组件之间共享数据有四种方法。

Props

它们将数据从父组件传递到子组件。

上下文

祖先组件可以用它们来使数据用于后代组件。

存储

它们将数据存储在所有组件外,并使其对所有组件可用。

模块范围

它们将数据存储在组件模块中,并使数据可用于组件的所有实例。

这些内置方法非常有用,实际上你都不需要状态管理库。

Props

组件可以通过 props 接受输入。它们被指定为父组件渲染的组件元素上的属性。例如,父组件可以执行以下操作:

<script>import Hello from './Hello.svelte';
</script><Hello name="Mark" />

这里 name prop 的值是字面量字符串。

作为 JavaScript 表达式或非字符串字面量的 prop 值必须用大括号括起来,不能用引号。

src/Hello.svelte 中定义的子组件可以这样做:

<script>export let name = 'World';
</script><div>Hello, {name}!
</div>

这里使用 export 关键字在组件的<script>部分中声明 props。这里用 Svelte 特有的方式使用了有效的 JavaScript 语法。

由于父元素可以更改值,因此必须使用 let 关键字而不是 const。为 props 分配默认值是可选的。

目前 Svelte 没有像 React、Vue 和 Angular 那样(通过 TypeScript)进行 prop 类型检查的功能。

属  性 

元素的属性值可以用 JavaScript 表达式提供。其语法为:

<element-name attribute-name =“ expression” />

表达式也可以嵌入到字符串值中。例如:

<Person fullName="{firstName} {middleInitial}. {lastName}" />

当属性值位于与该属性同名的变量中时,可以使用简写语法。例如:

<Person {fullName} />

如果多个属性位于一个对象中,则可以使用散布运算符插入多个属性,其中键是属性名称,值是它们的值。例如:

<script>let score = 0;const inputAttrs = {type: 'number',max: 10,min: 0,value: score};
</script><input {...inputAttrs} bind:value={score} />

上面的示例使用 bind 模拟双向数据绑定。这将在后文详细说明。

样  式 

.svelte 文件的style标记中的样式将自动确定组件的范围。

Svelte 将生成的相同的 CSS 类名称(svelte-hash)添加到可能受这些 CSS 规则影响的组件的每个渲染元素中,从而实现了作用域。

全局样式应在 public/global.css 中定义。

与标准 CSS 一样,样式标记中的注释必须使用 / * */ 注释定界符。

"svelte3” ESLint 插件会对未使用的 CSS 选择器发出警告。

可以有条件地将 CSS 类添加到元素。在以下示例中,仅当 status 大于零时才添加 CSS 类 error。

<div class:error={status > 0}>{result}</div>
导入组件

组件可以在其<script>标记内导入其他组件。例如:

import Other from './Other.svelte';

可以在组件的 HTML 部分中使用导入的组件。

插入 HTML

要渲染一个值为 HTML 字符串的 JavaScript 表达式,请使用语法{@html expression}

假设 markup 是一个包含 HTML 字符串的变量。下面的代码将渲染它:

<p>{@html markup}</p>

为了避免跨站点脚本,请 escape 不受信任来源中的 HTML。

反应性 

插值中引用的顶级变量的更改会自动导致这些插值被重新计算。例如:

<script>let count = 0;const increment = () => count++;
</script><div>count = {count}</div>
<button on:click={increment}>+</button>

必须分配一个新值以触发此操作。将新元素推送到数组上不会触发它。可以使用以下方法:

myArr = myArr.concat(newValue);// 另一种技巧
myArr.push(newValue);
myArr = myArr;
响应式声明

在 JavaScript 语句开头写一个名称,后面跟一个冒号,就会创建一个 标签语句。标签语句可以用作 break 和 continue 语句的目标。

有趣的是,在同一范围的多个语句中使用相同的标签名称在 JavaScript 中不是错误。当这个语法用在顶层语句(未嵌套在函数或块中)上且名称为美元符号时,Svelte 会将顶层语句视为 响应式声明

这是 Svelte 编译器以特殊方式处理有效的 JavaScript 语法的另一个例子。当这类语句引用的任何变量的值更改时,它们自己就会重复。这有点像 Vue 中的 计算属性。例如:

// average 的值一开始就被计算
// 如果 total 或 count 的值更改就重新计算。
$: average = total/count;// count 的值输出在 devtools 控制面板中
// 当这个语句执行和每次更改时。
// 这方便了调试工作!
$: console.log('count =', count);

将 $: 应用于未声明变量的赋值时(比如上面的 average 赋值),不允许使用 let 关键字。$: 可以应用于一个块。例如:

$: {// 这里是要重复的语句
}

这也可以应用于多行语句,比如 if 语句。例如:

$: if (someCondition) {// 主体语句
}

如果条件或主体中引用的任何变量发生更改,上面的示例就会执行,但只有在条件为 true 时主体才执行。例如,如果条件包括对函数的调用,则如果主体中的任何引用发生更改就会调用它们。

Markup 中的逻辑
在 markup 中添加条件逻辑和迭代逻辑有三种常见方法。
  1. React 使用 JSX,其中逻辑由大括号中的 JavaScript 代码实现。
  2. Angular 和 Vue 支持特定于框架的逻辑属性。例如,Angular 支持 ngIf 和 ngFor,而 Vue 支持 v-if 和 v-for。
  3. Svelte 支持包装元素的类似 Mustache 的自定义语法。例如{#if}和{#each}。

IF 语句

Svelte 的条件逻辑以{#if condition}开始。开头的 # 表示块的起始标记。用{/ if}标记结尾。开头的 / 表示块的结束标记。有条件渲染的 markup 位于这两者之间。它们之间可以包含的其他块标记有{:else if condition}和{:else}。开头的: 表示块的继续标记。例如:

{#if color === 'yellow'}<div>Nice color!</div>
{:else if color === 'orange'}<div>That's okay too.</div>
{:else}<div>Questionable choice.</div>
{/if}

虽说这里的语法乍看起来似乎很奇怪,但它确实能有条件地渲染多个元素。Angular/Vue 中向元素添加特殊属性的方法需要指定一个公共父元素。

Each 语句

Svelte 的迭代从{#each iterable as element}开始。用{/each}标记结尾。每个元素要渲染的 markup 放在两者之间。一般来说可迭代的是数组,但任何可迭代的值都能用。{:else}之后的内容在可迭代内容为空时渲染。例如,假设变量 colors 设置为 ['red', 'green', 'blue']:

<!-- 分开行来使用 color 输出每种颜色。-->
{#each colors as color}<div >{color}</div>
{/each}<!-- 在单独的行上输出每种颜色,并在其前面从 1 开始的位置后跟括号。-->
{#each colors as color, index}<div>{index + 1}) {color}</div>
{/each}<!-- 这里使用解构来在"people"的对象中获取特定的属性。-->
{#each people as {name, age}}<div>{name} is {age} years old.</div>
{:else}<div>There are no people.</div>
{/each}

如果要添加、删除或修改列表中的项目,则应为每个元素提供唯一的标识符。这类似 React 和 Vue 中所需的 key prop。

在 Svelte 中,唯一标识符是 #each 语法的一部分,而不属于元素 prop。在以下示例中,每个 person 的唯一标识符是对应的 id 属性。

{#each people as person (person.id)}<div>{person.name} is {person.age} years old.</div>
{/each}
Promise

Svelte 提供了 markup 语法来等待 promise 解析或拒绝。它可以根据 promise 的未完成、已解析或已拒绝的状态提供不同的输出。

以下示例假定组件具有返回 Promise 的 getData 函数。在:then 和:catch 之后可以使用任何变量名来接收解析或拒绝的值。

{#await getData()}<div>Waiting for data ...</div>
{:then result}<div>result = {result}</div>
{:catch error}<div class="error">Error: {error.message}</div>
{/await}

下一个示例在等待 Promise 解析时省略了要渲染的 markup。:catch 部分也可以省略。

{#await getData() then result}<div>result = {result}</div>
{:catch error}<div class="error">Error: {error.message}</div>
{/await}
插  槽 

插槽允许子内容传递到组件。接收组件可以决定是否渲染它,在何处渲染。请注意,空格算作子内容。接收组件可以标记使用渲染所有子内容的位置。这称为 默认插槽

它还可以为没有向插槽提供内容的父元素提供默认内容来渲染。例如,<slot>Thanks for nothing!</slot>

命名插槽允许父元素提供多组内容,接收组件可以针对这些内容决定是否渲染以及在何处渲染。父元素使用 slot 属性标识它们。子元素则定义它们在何处用带有匹配的 name 属性的 slot 元素来渲染。

下面是来自父元素的 HTML 示例,该 HTML 元素的目标是子元素 ShippingLabel 中的多个命名槽:

<ShippingLabel><div slot="address">123 Some Street,<br />Somewhere, Some State 12345</div><div slot="name">Mark Volkmann</div>
</ShippingLabel>

这是 ShippingLabel.svelte:

<style>label {display: block;font-weight: bold;}
</style><div><label>Ship To:</label><slot name="name">unknown</slot><slot name="address" />
</div>
绑定表单元素

inputtextareaselect这样的表单元素可以绑定到变量上。这将模拟双向数据绑定。

除了提供当前值之外,双向数据绑定还提供事件处理,以便在用户更改表单元素值时更新变量。

对于类型为 number 或 range 的input元素,双向数据绑定会自动将值从字符串强制转换为数字。例如,考虑以下 HTML 表单:

640?wx_fmt=jpeg

这是使用单个 Svelte 组件的实现。注意在多处使用了 bind:。

<script>const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];const flavors = ['vanilla', 'chocolate', 'strawberry'];const seasons = ['Spring', 'Summer', 'Fall', 'Winter'];let favoriteColor = '';let favoriteFlavors = [];let favoriteSeason = '';let happy = true;let name = '';let story = '';
</script><style>div {margin-bottom: 10px;}input,select {border: solid gray 1px;border-radius: 4px;padding: 4px;}input[type='checkbox'],input[type='radio'] {margin-left: 5px;}label {display: inline-block;font-weight: bold;margin-right: 5px;vertical-align: top;}
</style><div class="form"><div><label>Name</label><input type="text" bind:value={name} /></div><div><label>Happy?</label><!-- 对于 checkbox, 要绑定到"checked"属性而非"value"上。--><input type="checkbox" bind:checked={happy} /></div><div><label>Favorite Flavors</label>{#each flavors as flavor}<label><!-- 使用"bind:group"和一组相关的 checkbox使值成为一组字符串。--><input type="checkbox" value={flavor} bind:group={favoriteFlavors} />{flavor}</label>{/each}</div><div><label>Favorite Season</label>{#each seasons as season}<label><!-- 使用"bind:group"和一组相关的 radio 按钮使值成为单个字符串。--><input type="radio" value={season} bind:group={favoriteSeason} />{season}</label>{/each}</div><div><label>Favorite Color</label><!-- 要将选项更改为可滚动列表以启用多重选项,添加"multiple"属性。--><select bind:value={favoriteColor}><option />{#each colors as color}<!-- <option> 元素可以有一个"value"属性其值可以是字符串、数字或对象。--><option>{color}</option>{/each}</select></div><div><label>Life Story</label><textarea bind:value={story} /></div><!-- 这里报告了绑定设置的变量值,但前提是 name 有值。-->{#if name}<div>{name} likes {favoriteColor}, {favoriteSeason},and is {happy ? 'happy' : 'unhappy'}.</div><div>{name}'s favorite flavors are {favoriteFlavors}.</div><div>Story: {story}</div>{/if}
</div>

除了绑定到基本变量之外,表单元素还可以绑定到对象属性。然后用户输入会使这些对象发生突变。

绑定定制 props 

Svelte 可以将子组件 prop 绑定到父组件中的变量。这将允许子组件更改父组件变量的值。例如,这是父组件:

<script>import Child from './Child.svelte';let pValue = 1;
</script><div>pValue = {pValue}</div>
<Child bind:cValue={pValue} />

这是子组件:

<script>export let cValue = '';const double = () => (cValue *= 2);
</script><div>cValue = {cValue}</div>
<button on:click={double}>Double</button>

按下 Child 组件中的按钮时,cValue 会加倍,并且加倍的值由于绑定到 cValue 而成为 pValue 的新值。

事件处理

事件处理由 on:event-name 属性指定,该属性的值是调度事件时要调用的函数。事件名称可以是标准 DOM 事件或自定义事件的名称。事件对象将传递给给定的函数。例如:

<!-- 函数 "handleClick" 必须在上面的<script>部分中定义。-->
<button on:click={handleClick}>Press Me</button><!-- 这里用匿名函数展示了内联事件处理。它为按钮设置了变量"clicked"到 DOM 元素。-->
<button on:click={event => clicked = event.target}>Press Me</button>

可以为同一个事件指定多个事件处理函数,并且在分派事件时将分别调用每个函数。例如:

<button on:click={doOneThing} on:click={doAnother}>Press Me</button>

事件处理程序可以使用修饰符名称前面的竖线指定任意数量的事件修饰符。例如:

<button on:click|once|preventDefault={handleClick}>Press Me</button>

支持的修饰符有:capture它导致处理程序函数仅在捕获阶段,而不是默认的冒泡阶段被调用。once它将在第一次发生事件后删除处理程序。passive它可以提高滚动性能。preventDefault它可以防止事件的默认操作发生。例如,它可以停止表单提交。stopPropagtion它可以防止捕获 / 冒泡流程中的后续处理程序被调用。

从 on: 属性中省略事件处理函数可以快速将事件转发到父组件。例如,假设组件结构的一部分是 A> B> C,并且 C 发出事件“foo”。B 可以使用<C on:foo/>将其转发到 A。请注意,on: 属性没有值。此方法也可以用于转发 DOM 事件。

组件可以调度事件。例如:

<script>import {createEventDispatcher} from 'svelte';// 组件实例化时必须调用,// 可选或稍后调用都不行。const dispatch = createEventDispatcher();function sendEvent() {// 事件关联的数据可以是一个原语或对象。// 事件名称不应包含横线。dispatch('someEventName', optionalData);}
</script>

这些事件仅转到父组件。它们不会自动在组件结构中冒泡。

父组件使用 on: 侦听子组件的事件。例如,如果父组件定义了函数 handleEvent,则它可以在 Child 组件分派具有给定名称的事件时注册要调用的函数。

<Child on:someEventName = {handleEvent} />
生命周期函数
Svelte 支持在组件实例的生命周期中发生四个特定事件时调用注册函数。这些事件包括:
  1. 已挂载时。
  2. 更新前。
  3. 更新后。
  4. 被销毁时。

术语“已挂载”表示已将组件实例添加到 DOM。术语“被销毁”表示该组件实例已从 DOM 中删除。要为这些事件注册函数,请从 svelte 包中导入所提供的生命周期函数。

import {afterUpdate, beforeUpdate, onDestroy, onMount} from 'svelte';

然后调用这些函数,并在事件发生时向它们传递要调用的函数。

最常用的生命周期函数是 onMount。一种用法是将焦点移至给定的表单元素。另一种用途是从 REST 服务检索组件所需的数据。

下面是一个移动焦点的示例。

<script>import {onMount} from 'svelte';let name = '';let nameInput;onMount(() => nameInput.focus());
</script><input bind:this={nameInput} bind:value={name} />

属性 bind:this 会将指定为其值的变量设置为对 input 的 DOM 元素的引用。这在传递给 onMount 的函数中使用,以将焦点移至 input。

从 DOM 中删除组件实例时,使用 onDestroy 注册要调用的函数的另一种方法是从通过 onMount 注册的函数返回该函数。这种方法有点像 React 中的 useEffect hook,不同之处在于 Svelte 中传递给 useEffect 的函数在挂载和更新时都运行。

生命周期函数可以从辅助函数中调用。这些可以在单独的.js 文件中定义,从而导入它们并用于多个组件。这很像定义自定义的 React hooks。

建议以“on”开头命名这些辅助函数,就像 React hook 名称以“use”开头那样。

动  作 

将特定元素添加到 DOM 时,动作(Action) 会注册要调用的函数。

动作是在具有属性 use:fnName = {args}的元素上指定的。已注册的函数将传递 DOM 元素和参数(如果存在)。如果不需要除元素以外的其他参数,则省略 = {args}。

这在某种程度上与 onMount 生命周期函数有关,该函数注册了将组件的每个实例添加到 DOM 时要调用的函数。将组件中的特定元素添加到 DOM 时,就将调用动作。例如:

<script>let name = '';const focus = element => element.focus();
</script><!-- 输入元素添加到 DOM 时调用焦点函数。-->
<input bind:value={name} use:focus />

动作函数可以选择返回具有 update 和 destroy 属性(也就是函数)的对象。这个功能不常用。

每当参数值更改时都会调用 update 函数。如果没有参数当然是不行的。

从 DOM 中删除元素时将调用 destroy 函数。

上下文

上下文(Context) 提供了一种替代方法,可以使用 props 和存储(接下来介绍)来使组件中的数据在其他组件中可用。上下文数据只能在后代组件中访问。

要在组件中定义上下文,请导入 setContext 函数并调用它,并提供上下文键和值。例如:

import {setContext} from 'svelte';// Must be called during component instantiation.
setContext('favorites', {color: 'yellow', number: 19});

要在后代组件中使用上下文,请导入 getContext 函数并调用它,并提供上下文键。这将从已使用该键定义上下文的最近的祖先组件获取上下文值。例如:

import {getContext} from 'svelte';// 组件实例化时必须调用。
const favorites = getContext('favorites');

上下文键可以是任何类型的值,不只是字符串。

上下文值可以是任何类型的值,包括具有后代组件可以调用的方法的对象和函数。

如果创建了上下文的组件再使用相同的键和不同的值调用 setContext,则后代组件将不会接收到更新。它们只能看到组件初始化期间可用的内容。

与 props 和存储不同,上下文不是响应式的。

下面是一个使用上下文使数据在后代组件中可用的示例。

<!-- In A.svelte -->
<script>import {setContext} from 'svelte';import B from './B.svelte';setContext('favorites', {color: 'yellow', number: 19});
</script><div>This is in A.<b ></b>
</div>
<!-- In B.svelte -->
<script>import C from './C.svelte';
</script><div>This is in B.<C />
</div>
<!-- In C.svelte -->
<script>import {getContext} from 'svelte';const {color, number} = getContext('favorites');
</script><div>This is in C.<div>favorite color is {color}</div><div>favorite number is {number}</div>
</div>

这将渲染以下内容:

This is in A.
This is in B.
This is in C.
favorite color is yellow
favorite number is 19

存  储 

存储(Stores) 在所有组件外部保持应用程序状态。它们是使用 props 或上下文来使数据在组件中可用的替代方法。

对于应该对所有组件可用的存储,请在 src/stores.js 之类的文件中定义并导出它们,并在需要时从该文件导入它们。

对于应该仅对给定组件的后代可用的存储,请在这个组件中定义它们,然后使用 props 或上下文将它们传递给后代。

Svelte 提供三种存储。
  1. 可写存储——这是唯一可以由组件修改的存储。
  2. 可读存储——这些存储处理它们自己的数据。
  3. 派生存储——这些存储从其他存储的当前值派生数据。

这些存储都有一个 subscribe 方法,该方法返回一个可调用的函数来 unsubscribe。也可以创建自定义存储。它们唯一的限制是成为具有正确实现的 subscribe 方法的对象。

示例:https://svelte.dev/tutorial/custom-stores

可写存储

要创建可写存储,请调用 svelte/store 包中定义的 writable 函数。然后传递初始值,还可以传递一个带有 set 函数的函数。如果传入了后者,它可以异步确定存储的值。例如,它可以调用 REST 服务,并将返回的值传递给 set。在第一个组件订阅存储之前不会调用此函数。

除了 subscribe 方法外,可写存储还有以下方法:
  • set(newValue)

这将为商店设置一个新值。
  • update(fn)

这将基于当前值更新存储值。fn 是一个传递当前值并返回新值的函数。

下面是仅使用初始值定义可写存储的示例。

// 在 stores.js 内
import {writable} from 'svelte/store';// 初始值是空数组。
export const dogStore = writable([]);

这是一个使用函数确定值来定义可写存储的示例。

// 在 stores.js 内
import {writable} from 'svelte/store';export const dogStore = writable(initialValue, async set => {// 订阅计数由 0 到 1 时调用。// 计算初始值并传递给 set 函数。const res = await fetch('/dogs');const dogs = await res.json();set(dogs);return () => {// 订阅计数归零时调用。};
});

可以将表单元素的值绑定到可写存储。当用户更改表单元素值时将更新存储。

<input bind:value={$someStore} />

存储名称上的 $ 前缀接下来会解释。

可读存储

要创建可读存储,请调用 svelte/store 包中定义的 readable 函数。

与可写存储一样,这里要为它传递一个初始值,还可以传递一个带有 set 函数的函数。例如:

import {readable} from 'svelte/store';export const dogStore = readable([], // 初始值。set => {const res = await fetch('/dogs');const dogs = await res.json();set(dogs);// 这里可以返回一个清理函数。}
);

set 函数可以使用 setInterval 来连续更改值。

使用存储
要开始使用存储,请选择下面一种方式来访问它:
  1. 作为 prop 接受它。
  2. 从上下文中获取它。
  3. 从.js 文件导入(适用于全局范围)。

有两种方法从存储中获取值:
  1. 在其上调用 subscribe 方法(有些冗长)。
  2. 使用自动订阅的捷径(通常是首选)。

下面是使用 subscribe 方法的示例。

<script>import {onDestroy} from 'svelte';import {dogStore} from './stores.js';let dogs;const unsubscribe = dogStore.subscribe(value => (dogs = value));onDestroy(unsubscribe);
</script><!-- 在 HTML 中使用 dogs。-->

下面是使用自动订阅的示例。

名称以 $ 开头的所有变量都必须放入存储。通过这种方法,组件在首次使用时会自动订阅存储,而被销毁时会自动取消订阅。

<script>import {dogStore} from './stores.js';
</script><!-- 在 HTML 中使用 $dogStore。-->

下面是更改可写存储的示例。

订阅存储的组件将看到更改。

<script>import {dogStore} from './stores.js';import Child from './Child.svelte';const dog = $dogStore;function changeDog() {// 方法 #1 - 创建新对象//dogStore.set({age: 2, breed: 'GSP', name: 'Oscar'});// 方法 #2 - 调整并复用对象dog.age = 2;dog.breed = 'GSP';dog.name = 'Oscar';dogStore.set(dog);}
</script><h1>Store Demo</h1>
<Child />
<button on:click={changeDog}>Change Dog</button>

下面是一个使用 HTML 中的 $ 引用从存储中获取更改的示例。

<script>import {dogStore} from './stores.js';
</script><div>{$dogStore.name} is a {$dogStore.breed} that is {$dogStore.age} years old.
</div>

下面的代码效果同上,但是使用 JavaScript 代码从存储中获取数据。

<script>import {dogStore} from './stores.js';// 这里需要 Parens 才能知道开放的大括号不是块的开头。$: ({age, breed, name} = $dogStore);
</script>
<div>{name} is a {breed} that is {age} years old.</div>
模块上下文(module context)

想要只在组件源文件中运行一次 JavaScript 代码,而不是为创建的每个组件实例都运行一次代码,请将代码包含在指定模块上下文的 script 标记中。

<script context="module">...
</script>

如果 script 标记未指定其上下文,则它为 实例上下文

两种 script 标记(实例和 模块上下文)都可以出现在组件源文件中。

两种上下文中都可以导出值。无法指定默认导出,因为组件本身会自动成为默认导出。

模块上下文可以声明变量并定义函数。这些可以在组件所有实例的实例上下文中访问,但它们不是响应式的。组件更改时不会重新渲染。这样就能在所有实例之间共享数据。

实例上下文变量和函数在模块上下文中不可访问。

请注意,不需要将不访问组件状态的函数移至模块上下文,因为(根据 Svelte API 文档)“ Svelte 将从组件定义中提升所有不依赖本地状态的函数。” 但将函数放在模块上下文中的一个目的是从外部导出和调用它们。

批处理 DOM 更新

可以更改顶级组件变量的值来使组件状态无效。

根据 Svelte 文档,“当你使 Svelte 中的组件状态无效时,它不会立即更新 DOM。相反,它会等到下一个微任务才查看是否需要应用其他任何更改(包括在其他组件中)。这样做避免了不必要的工作,并使浏览器可以更有效地对事物进行批处理。”

tick 函数“返回一个 promise,该 promise 将在任何未决状态更改应用于 DOM 时立即解析(如果没有未决状态更改,则立即解析)。”

应用 DOM 更新后,可以使用此方法进行其他状态更改。

<script>import {tick} from 'svelte';...// 做一些状态更改。// 下面的内容预防 tick 调用后的批量更新。await tick();// DOM 更新后做更多状态更改。...
</script>

调用 await tick() 在测试中也很有用,可以在测试效果之前等待更改被处理。

动画
Svelte 提供了许多功能用来轻松将动画添加到元素。以下是它提供的一些函数和过渡效果值。
  • svelte/animate 包提供了 flip 函数。
  • svelte/motion 包提供 spring 和 tweened 函数。
  • svelte/transition 包提供了 crossfade 函数及过渡值 draw(用于 SVG 元素)、fade、fly、scale 和 slide。
  • 另请参见 svelte/easing 包,这个包提供了控制动画随时间变化的速率的缓动函数。

下面是一个基本的动画示例,其中有一个列表项在装载时淡入并在销毁时淡出。

<script>import {fade} from 'svelte/transition';
</script><li transition:fade><!-- 一些内容 -->
</li>

可以创建自定义动画。

示例:https://svelte.dev/tutorial/custom-css-transitions

组件可以侦听事件,以了解过渡何时开始和结束。需要侦听的事件有:
  • introstart 和 introend。
  • outrostart 和 outroend。

    特殊元素

Svelte 支持几种特殊元素,其形式为<svelte:name props>。总结如下。

<svelte:component this = {expression} optionalProps>

它将渲染 expression 指定的组件。如果 expression 是虚值则不渲染任何内容。可选的 props 会被传递到要渲染的组件。

<svelte:self props>

它允许组件渲染其自身的实例。它支持递归组件,这是必需的,因为组件无法导入自身。

<svelte:window on:eventName={handler}>

它将注册一个由 DOM window 对象调度给定事件时要调用的函数。resize 事件就是一个例子。

<svelte:window bind:propertyName={variable}>

它会将变量绑定到 window 属性。一个例子是 innerWidth。

<svelte:body on:eventName={handler}>

当 DOM body 元素调度给定事件时,此方法注册一个要调用的函数。例子包括 mouseEnter 和 mouseLeave。

<svelte:head>elements</svelte:head>

它会将元素插入 DOM 文档的 head 元素中。例子包括插入 link 和 script 标记。

<svelte:options option={value} />

它位于.svelte 文件的顶部,而不是 script 标记内部。它指定了编译器选项,包括:

immutable

它意味着 props 将被视为不可变的,从而提供了优化。

默认值为 false。不可变意味着父组件将为对象 props 创建新对象,而不是修改现有对象的属性。这使 Svelte 可以通过对比对象引用(而不是对象属性)来确定 prop 是否已更改。

当此选项设置为 true 时,如果父组件修改了子组件的对象属性,则子组件将不会检测到更改并且不会重新渲染。

accessors

它为组件 props 添加了 getter 和 setter 方法。默认为 false。将 Svelte 组件编译为非 Svelte 应用程序中使用的自定义元素时,这个方法很有用。

namespace="value"

它指定了组件的命名空间。一种用途是为 SVG 组件指定命名空间 svg。

tag="value"

它指定将 Svelte 组件编译为自定义元素时要使用的名称。它允许 Svelte 组件用作非 Svelte 应用程序中的自定义元素。

调  试 

当给定变量更改时,使用 @debug 中断,并在 devtools 控制台中输出它们的值。将其放置在 HTML 部分的顶部,不要放在script标记内部。例如:

{@debug var1, var2, var3}

被监视的变量可以具有任何类型的值,包括对象。要在所有状态更改时中断,请省略变量名称。

{@debug}
ESLINT 

ESLint 称自己为“针对 JavaScript 和 JSX 的可插入式 linting 实用程序”。它可以报告许多语法错误和潜在的运行时错误。它还可以报告与指定编码准则的差异。

要在 Svelte 项目中安装 ESLint 所需的全部内容,请输入 npm install -D name,其中 name 为:
  • eslint
  • eslint-plugin-svelte3

创建具有以下内容的.eslintrc.json 文件:

{"env": {"browser": true,"es6": true,"jest": true},"extends": ["eslint:recommended", "plugin:import/recommended"],"globals": {"cy": "readonly"},"overrides": [{"files": ["**/*.svelte"],"processor": ["svelte3/svelte3"]}],"parserOptions": {"ecmaVersion": 2019,"sourceType": "module"},"plugins": ["svelte3"],"rules": {"no-console": "off"}
}

将以下 npm 脚本添加到 package.json:

"lint": "eslint --fix --quiet src --ext .js,.svelte",

要运行 ESLint,请输入 npm run lint。

有关针对 Svelte 的 ESLint 选项的更多信息,请参见 https://github.com/sveltejs/eslint-plugin-svelte3。

Prettier 

Prettier 称自己为“经过优化的 JavaScript 格式化程序”。它支持多种语言和语言功能,包括 ES2017、TypeScript、JSON、HTML、CSS、LESS、SCSS、JSX、Vue 和 Markdown。

要在 Svelte 项目中安装 Prettier 所需的全部内容,请输入 npm install -D name,其中 name 为:
  • prettier
  • prettier-plugin-svelte

Svelte ESLint 插件强制按scriptstyle和 HTML 的顺序执行。将以下 npm 脚本添加到 package.json:

"format": "prettier --write '{public,src}/**/*.{css,html,js,svelte}'",

要运行 Prettier,请输入 npm run format。

ToDo 应用

下面来看一个简单的 Todo 应用程序的实现,正好过一遍最重要的那些 Svelte 概念。

代码链接:https://github.com/mvolkmann/svelte-todo

640?wx_fmt=jpeg

要添加新的待办事项时,需要在输入框中输入待办事项的文本,然后按“添加”按钮或 Enter 键。

要将待办事项在已完成和未完成的状态之间切换,需要单击其左侧的复选框。请注意,顶部附近的“remaining”文本显示当前未检查的待办事项数和待办事项总数。

要删除待办事项,需要单击其右侧的“Delete”按钮。

要存档所有已检查的待办事项,需要单击“Archive Completed”按钮。但这个版本的应用并不会真的存储它们,其实它们都被删掉了。

下面是文件 src/main.js,它在文档主体中渲染 TodoList 组件来启动应用程序。

import TodoList from './TodoList.svelte';const app = new TodoList({target: document.body});export default app;

下面是文件 src/Todo.svelte 中 Todo 组件的代码。

它是一个包含以下内容的列表项:
  • 待办事项文本。
  • 一个复选框。
  • 一个“Delete”按钮。

它需要一个名为“todo”的 prop 来保存待办事项的文本。切换复选框后,它将调度一个“toggleDone”事件。按下“Delete”按钮时,它将调度一个“删除”事件。

<script>import {createEventDispatcher} from 'svelte';const dispatch = createEventDispatcher();export let todo; // 唯一的 prop
</script><style>/* 在 todo 的文本上画一条线标记其完成状态。*/.done-true {color: gray;text-decoration: line-through;}li {margin-top: 5px;}
</style><li><inputtype="checkbox"checked={todo.done}on:change={() => dispatch('toggleDone')}/><span class={'done-' + todo.done}>{todo.text}</span><button on:click={() => dispatch('delete')}>Delete</button>
</li>

下面是文件 src/TodoList.svelte 中 TodoList 组件的代码。

看到这里,关于 Svelte 你已经很熟悉了,所以这些代码应该很容易看懂。

<script>import Todo from './Todo.svelte';let lastId = 0;// 创建一个 todo 对象。const createTodo = (text, done = false) => ({id: ++lastId, text, done});let todoText = '';// 应用程序初始有两个 todo 项目。let todos = [createTodo('learn Svelte', true),createTodo('build a Svelte app')];let uncompletedCount = 0;// 这是"响应式声明"。// 它保证未完成的代码在 todo 数组修改时被更新。$: uncompletedCount = todos.filter(t => !t.done).length;// 这是另一个"响应式声明"。// 保证当 uncompletedCount 或 todo 数组更改时状态随时更新$: status = `${uncompletedCount} of ${todos.length} remaining`;// 创建并添加一个新的 todo.function addTodo() {// 回想这里为何必须使用 concat 代替 push。todos = todos.concat(createTodo(todoText));todoText = ''; // 清空 input}// 删除全部标记为完成的 todo。const archiveCompleted = () => (todos = todos.filter(t => !t.done));// 删除特定 todo。const deleteTodo = todoId => (todos = todos.filter(t => t.id !== todoId));// 改变给定 todo 的状态。function toggleDone(todo) {const {id} = todo;todos = todos.map(t => (t.id === id ? {...t, done: !t.done} : t));}
</script><style>button {margin-left: 10px;}/* 从加点(·)列表中移除点。*/ul.unstyled {list-style: none;margin-left: 0;padding-left: 0;}
</style><div><h2>To Do List</h2><div>{status}<button on:click={archiveCompleted}>Archive Completed</button></div><br /><!-- 我们不想真的提交表单。使用表单使得按下 enter 键时触发"Add"按钮。--><form on:submit|preventDefault><inputtype="text"size="30"autofocusplaceholder="enter new todo here"bind:value={todoText}/><button disabled={!todoText} on:click={addTodo}>Add</button></form><ul class="unstyled">{#each todos as todo}<Todotodo={todo}on:delete={() => deleteTodo(todo.id)}on:toggleDone={() => toggleDone(todo)}/>{/each}</ul>
</div>
单元测试

Svelte 组件的单元测试可以使用 Jest 实现。另外建议使用“Svelte 测试库”。它与 Jest 协作,可以简化 Svelte 组件的单元测试编写。

本文不会深入探究这些测试工具的细节,但下面提供了测试代码示例。要了解这些工具的更多信息,请访问:

https://jestjs.io/

https://testing-library.com/

要安装所需的全部内容,请输入 npm install -D name,其中 name 为:
  • @babel/core
  • @babel/preset-env
  • @testing-library/svelte
  • babel-jest
  • jest
  • jest-transform-svelte

使用以下内容创建文件 babel.config.js:

module.exports = {presets: [['@babel/preset-env',{targets: {node: 'current'}}]]
};

如果未按上面所示设置 targets.node,则在运行测试时将显示错误消息“regenerator-runtime not found”。

使用以下内容创建文件 jest.config.js:

module.exports = {transform: {'^.+  .js$': 'babel-jest','^.+  .svelte$': 'jest-transform-svelte'},moduleFileExtensions: ['js', 'svelte'],bail: false,verbose: true
};

将 bail 设置为 false 意味着 Jest 在某个测试失败时不应退出测试套件。

将 verbose 设置为 true 会使 Jest 显示每个测试的结果,而不只是各个测试套件的结果摘要。

将以下 npm 脚本添加到 package.json:

"test": "jest --watch src",

要运行单元测试,请输入 npm test。

以下是用于测试文件 src/Todo.spec.js 中 Todo 组件的代码:

import {cleanup, render} from '@testing-library/svelte';import Todo from './Todo.svelte';describe('Todo', () => {const text = 'buy milk';const todo = {text};// 卸载之前测试中挂载的所有组件。afterEach(cleanup);test('should render', () => {const {getByText} = render(Todo, {props: {todo}});const checkbox = document.querySelector('input[type="checkbox"]');expect(checkbox).not.toBeNull(); // 找到复选框expect(getByText(text)); // 找到 todo 文本expect(getByText('Delete')); // 找到 Delete 按钮});// 测试事件在 checkbox 状态更改或"Delete"按钮按下时是否 fired 没有捷径。// 它们由 TodoList.spec.js 的测试覆盖。
});

以下是用于测试文件 src/TodoList.spec.js 中 TodoList 组件的代码:

import {tick} from 'svelte';
import {cleanup, fireEvent, render, wait} from '@testing-library/svelte';import TodoList from './TodoList.svelte';describe('TodoList', () => {const PREDEFINED_TODOS = 2;afterEach(cleanup);// 它被下面的很多测试函数使用。function expectTodoCount(count) {return wait(() => {// 每个 todo 有一个<li>根元素。const lis = document.querySelectorAll('li');expect(lis.length).toBe(count);});}test('should render', async () => {const {getByText} = render(TodoList);expect(getByText('To Do List'));expect(getByText('1 of 2 remaining'));expect(getByText('Archive Completed')); // 按钮await expectTodoCount(PREDEFINED_TODOS);});test('should add a todo', async () => {const {getByTestId, getByText} = render(TodoList);const input = getByTestId('todo-input');const value = 'buy milk';fireEvent.input(input, {target: {value}});fireEvent.click(getByText('Add'));await expectTodoCount(PREDEFINED_TODOS + 1);expect(getByText(value));});test('should archive completed', async () => {const {getByText} = render(TodoList);fireEvent.click(getByText('Archive Completed'));await expectTodoCount(PREDEFINED_TODOS - 1);expect(getByText('1 of 1 remaining'));});test('should delete a todo', async () => {const {getAllByText, getByText} = render(TodoList);const text = 'learn Svelte'; // 第一个 todoexpect(getByText(text));const deleteBtns = getAllByText('Delete');fireEvent.click(deleteBtns[0]); // 删除第一个 todoawait expectTodoCount(PREDEFINED_TODOS - 1);});test('should toggle a todo', async () => {const {container, getByText} = render(TodoList);const checkboxes = container.querySelectorAll('input[type="checkbox"]');fireEvent.click(checkboxes[1]); // 第二个 todoawait tick();expect(getByText('0 of 2 remaining'));fireEvent.click(checkboxes[0]); // 第一个 todoawait tick();expect(getByText('1 of 2 remaining'));});
});
端到端测试

可以使用 Cypress 来实现 Svelte 应用程序的端到端测试。本文不会深入探究 Cypress 的细节,但是下面提供了测试代码示例。

要了解有关 Cypress 的更多信息,请访问 https://www.cypress.io/。

要安装Cypress,请输入npm install -D cypress。

将以下 npm 脚本添加到 package.json:

"cy:open": "cypress open",
"cy:run": "cypress run",

要以交互方式启动 Cypress 测试工具,请输入 npm run cy:open。如果尚不存在 cypress 目录,它还会创建一个带有以下子目录的目录:

fixtures

这个目录可以保存测试使用的数据。数据通常在导入到测试的.json 文件中。

integration

你的测试文件在此目录的顶部或子目录中。

plugins

此目录扩展了 Cypress 的功能。在运行每个规范文件之前,Cypress 会自动在该目录的 index.js 文件中运行代码。

screenshots

这个目录存放屏幕截图,截图通过调用 cy.screenshot() 生成。这在调试测试时很有用。

support

此处的文件会添加自定义的 Cypress 命令,使它们在测试中可用。在运行每个规范文件之前,Cypress 会自动在该目录的 index.js 文件中运行代码。

这些目录中装有示例文件,所有示例文件都可以删除。

在 cypress/integration 目录下创建带有.spec.js 扩展名的测试文件。

要运行端到端测试:
  1. 使用 npm run dev 启动应用程序服务器。
  2. 输入 npm run cy:open。
  3. 按下 Cypress 工具右上角的“Run all specs”按钮。

这将打开一个浏览器窗口,在其中运行所有测试。完成测试后,关闭此浏览器窗口和 Cypress 工具。

以下是文件 cypress/integration/TodoList.spec.js 中 Todo 应用程序的端到端测试代码。

const baseUrl = 'http://localhost:5000/';describe('Todo app', () => {it('should add todo', () => {cy.visit(baseUrl);cy.contains('1 of 2 remaining');// "Add"按钮应被禁用,直到文本输入后才解除。cy.contains('Add').as('addBtn').should('be.disabled');// 输入 todo 文本。const todoText = 'buy milk';cy.get('[data-testid=todo-input]').as('todoInput').type(todoText);cy.get('@addBtn').should('not.be.disabled');cy.get('@addBtn').click();cy.get('@todoInput').should('have.value', '');cy.get('@addBtn').should('be.disabled');cy.contains(todoText);cy.contains('2 of 3 remaining');});it('should toggle done', () => {cy.visit(baseUrl);cy.contains('1 of 2 remaining');// 找到第一个 checkbox 并打勾。cy.get('input[type=checkbox]').first().as('cb1').click();cy.contains('2 of 2 remaining');// 转换同一个 checkbox。cy.get('@cb1').check();cy.contains('1 of 2 remaining');});it('should delete todo', () => {cy.visit(baseUrl);cy.contains('1 of 2 remaining');const todoText = 'learn Svelte'; // 第一个 todocy.contains('ul', todoText);// 点击第一个"Delete"按钮。cy.contains('Delete').click();cy.contains('ul', todoText).should('not.exist');cy.contains('1 of 1 remaining');});it('should archive completed', () => {cy.visit(baseUrl);const todoText = 'learn Svelte'; // 第一个 todocy.contains('ul', todoText);// 点击"Archive Completed"按钮。cy.contains('Archive Completed').click();cy.contains('ul', todoText).should('not.exist');cy.contains('1 of 1 remaining');});
});

要重新运行测试,请单击浏览器窗口顶部附近的圆形箭头按钮。

为了更好地调试,请在应用程序代码中添加 console.log 调用,然后在运行测试的浏览器窗口中打开 devtools 控制台。

将更改保存到应用程序源文件或测试文件时,测试将自动重新运行。

要以命令行模式启动 Cypress 测试工具,请输入 npm run cy:run。这将在终端窗口中输出测试结果,记录测试运行的视频,并输出视频的文件路径。双击视频文件即可观看。

相关工具
以下是推荐读者研究的 Svelte 相关工具。
  • Svelte VS Code 扩展
  • Sapper

这是“由 Svelte 支持的应用程序框架”。Sapper 是一名士兵,负责诸如修建和维修道路和桥梁,铺设和清除地雷等任务。Sapper 类似 Next 和 Gatsby。它提供路由、服务端渲染和代码拆分功能。
  • Svelte Native

这是一个社区推动的项目,支持使用 Svelte 实现原生移动应用程序。它基于 nativescript-vue。
  • Svelte GL

这是 Three.js 3D 图形库的 Svelte 版本,正在开发中。
  • 带 Svelte 的 Storybook

Storybook 是用于演示和试验 Web UI 组件的工具。

总  结 

到这里就结束了!Svelte 是当前流行的 React、Vue 和 Angular 框架的很好的替代品。它有许多好处,包括较小的包体积、简单的组件定义、方便的状态管理以及无需虚拟 DOM 的反应性。

非常感谢 Charles Sharp 和 Kristin Kroeger 审阅本文!

英文原文

https://objectcomputing.com/resources/publications/sett/july-2019-web-dev-simplified-with-svelte

END

开发者技术前线 ,汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。

历史阅读

640?

640?wx_fmt=png
在看点一下
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. angular1.0初识

    Angular是一款来自谷歌的开源的web前端框架&#xff0c;Angular基于typescript&#xff0c;相比于其他两个框架&#xff0c;Angular更适合中大型企业级项目。 安装angular-cli脚手架&#xff1a; npm install -g angular/cli 或者 cnpm install -g angular/cli可以在已知目…...

    2024/5/3 3:52:38
  2. Angular开发Tips

    1、在使用$routeProvider的时候&#xff0c;需要让模块依赖ngRoute&#xff0c;否则会提示找不到服务&#xff0c;示例&#xff1a; angular.module(module1, [ngRoute]) .config([$routeProvider, function($routeProvider){//do something... }]);2、在页面中需要绑定有风险的…...

    2024/5/3 3:34:56
  3. 第三章 angular是怎么工作的

    注&#xff1a;学习使用&#xff0c;禁止转载 在这章中,我们会去讨论angular2中的高级概念,我们需要退一步,这样我们才能看清楚所有这些片段是怎么组装起来的. :fa-info-circle: 如果你使用angular1,你会发现angular2使用了不一样的基础模型,别慌,angular2的基础模型更加直接和…...

    2024/5/3 9:31:52
  4. angular4实战--简单的投票系统

    项目地址&#xff1a;https://github.com/xu1260114313/angular.git 完成后&#xff1a;1.通过node及npm安装angular-cli:npm install -g angular/cli 2.检测angular-cli是否安装成功&#xff1a;如果出现以上情况&#xff0c;则证明angular-cli创建成功&#xff01; 3.通过ang…...

    2024/4/21 2:59:45
  5. Angular实现 js 的 sort 方法

    sort() 方法用于对数组的元素进行排序&#xff0c;并返回数组。 默认排序顺序是根据字符串UniCode码。因为排序是按照字符串UniCode码的顺序进行排序的&#xff0c;所以首先应该把数组元素都转化成字符串&#xff08;如有必要&#xff09;&#xff0c;以便进行比较。 语法&am…...

    2024/4/21 2:59:44
  6. Angular知识梳理

    Tomato Angular做一些问题记录 目录 文章目录接口访问angular环境搭建及其常用语法常用备注Radio循环绑定值组件出入值路径跳转分页单选全选上传附件日期控件fromEvent监听事件angular树结构angular生成二维码angular引用js接口访问 接口路径调用修改proxy.conf.json 注意配…...

    2024/4/26 22:15:01
  7. Angular service 详解

    Angular为什么需要service组件应该是专注于展示层&#xff0c;所以需要service来获取数据和保存数据。组件之间的通信需要service来协助完成。众所周知&#xff0c;angular中service采用的是依赖注入&#xff0c;那什么是依赖注入呢&#xff1f;依赖注入&#xff08;DI&#xf…...

    2024/5/3 8:18:42
  8. angular学习之路12-响应式表单

    1,添加单个表单控件&#xff1a; 步骤 1 - 注册 ReactiveFormsModule 要使用响应式表单&#xff0c;就要从 angular/forms 包中导入 ReactiveFormsModule 并把它添加到你的 NgModule 的 imports 数组中。 import { ReactiveFormsModule } from angular/forms; NgModule({ …...

    2024/4/21 2:59:41
  9. Angular 问题解决 —— 实现切换 tab 时,保持 url 参数不变;ionic 阻止click事件冒泡和捕获,获取执行当前点击事件的元素:event.srcElement.tagName;

    目录 问题一&#xff1a;实现切换 tab 时&#xff0c;保持 url 参数不变 场景再现 问题解决 问题二&#xff1a;ionic 阻止 click事件 冒泡和捕获 问题一&#xff1a;实现切换 tab 时&#xff0c;保持 url 参数不变 场景再现 使用 Angular Ionic5 创建包含 tabs 的页面&#x…...

    2024/4/21 2:59:41
  10. angular.js ui-href 子元素和父元素的跳转互不影响——阻止冒泡

    遇到一个问题&#xff0c;在angular.js中&#xff0c;父元素的div有ui-href 的链接&#xff0c;子元素的button也有ui-href的链接&#xff0c;点击子元素的ui-href 跳转的却是父元素的链接&#xff0c;通过阻止冒泡解决这个问题&#xff0c;添加一个ng-click"$event.stopP…...

    2024/4/21 2:59:39
  11. angular ngClick 阻止冒泡和默认行为

    这其实是一个很简单的问题&#xff0c;如果你认真查看过Angular官方的API文档&#xff0c;本来不想记录的。但是这个问题不止一次的被人问起&#xff0c;所以今天在记录在这里。 在Angular中已经对一些ng事件如ngClick,ngBlur,ngCopy,ngCut,ngDblclick...中加入了一个变量叫做$…...

    2024/4/21 2:59:39
  12. AngularJs禁止冒泡事件

    $event.stopPropagation(); 今天看见一个比较恶心的需求&#xff0c;就是点击表格的 <tr> 第一格的 <input type"checkbox"> 选中&#xff0c;问题来了&#xff0c; 不知情的情况下去点击<input type"checkbox">会发现无法选中。 <…...

    2024/4/21 2:59:37
  13. 关于事件冒泡和键盘事件 以及与Angular的区别

    一、事件冒泡方法一、使用event.cancelBubble true来组织冒泡<div click"show2()"><input type"button" value"按钮" click"show1($event)"></div>methods:{show1:function(ev){console.log(ev);alert(1);ev.cance…...

    2024/4/21 2:59:36
  14. angular 禁止事件冒泡 和 默认行为

    事件冒泡和事件捕捉一直以来都是被讨论的话题&#xff0c;也许大家平时在工作中没有遇到过需要解决事件冒泡的情况举个例子&#xff1a; <body ng-click"fun1()"><div ng-click"fun2()"><img ng-click"fun3()" src"xxx.png…...

    2024/4/21 2:59:35
  15. ES6和React笔试题

    1、var、let、const之间的区别 var声明变量可以重复声明&#xff0c;而let不可以重复声明var是不受限于块级的&#xff0c;而let是受限于块级var会与window相映射&#xff08;会挂一个属性&#xff09;&#xff0c;而let不与window相映射var可以在声明的上面访问变量&#xff0…...

    2024/4/21 2:59:35
  16. React状态管理

    状态管理 传统MVC框架的缺陷 什么是MVC&#xff1f; [外链图片转存失败(img-5UKs5YTH-1563154546022)(./images/mvc-base.png)] MVC的全名是Model View Controller&#xff0c;是模型(model)&#xff0d;视图(view)&#xff0d;控制器(controller)的缩写&#xff0c;是一种…...

    2024/4/20 9:08:27
  17. React初探

    关于React&#xff0c;最近想花时间去了解学习&#xff0c;所以记录一些自己的学习内容。所有的内容只是自己的一些想法&#xff0c;不对的地方希望给与指正。 1. React关注于视图层 因为之前学习过Angular&#xff0c;所以习惯Angualr的MVC的模式。Controller作为Model和Vie…...

    2024/4/21 2:59:33
  18. React 和 Cordova的异同及应用

    #前端开发技术的调研 标签&#xff08;空格分隔&#xff09;&#xff1a; 未分类 标签&#xff1a; 移动开发 2018.1.6 文章目录React.js概述JSXVirtual DOMReact NativeReact Native 印象React Native工作原理Weex和Vue.jsReact Native、Weex和Cordova对比跨平台特性开发方式…...

    2024/5/2 16:47:10
  19. Web前端涵盖哪些知识 怎么区分Angular和React

    Web前端涵盖哪些知识&#xff1f;怎么区分Angular和React&#xff1f;对于一个Web前端工程师而言&#xff0c;框架知识非常重要&#xff0c;它对你项目的成功有着相当大的影响。一般学Web前端都会涵盖JS框架知识&#xff0c;比如Angular和React&#xff0c;下面就给大家讲解一下…...

    2024/4/20 20:14:44
  20. 常用前端框架Angular和React的一些认识

    为什么要用AngularJs&#xff1f; 要了解为什么使用AngularJS首先就要接受它的思想&#xff1a; 首先&#xff0c;angularJS借助了传统MVC的架构模式(model模型 view视图 controller控制器)&#xff1b;通过控制器来改变视图&#xff0c;再由视图来改变数据模型&#xff1b;它…...

    2024/4/20 20:14:42

最新文章

  1. 基于GWO灰狼优化的CNN-LSTM-Attention的时间序列回归预测matlab仿真

    目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1卷积神经网络&#xff08;CNN&#xff09;在时间序列中的应用 4.2 长短时记忆网络&#xff08;LSTM&#xff09;处理序列依赖关系 4.3 注意力机制&#xff08;Attention&#xff09; 4…...

    2024/5/3 11:22:18
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 【Ubuntu】在 Windows 和 Ubuntu 之间传输文件

    在 Ubuntu 上安装 Samba&#xff1a; sudo apt-get update sudo apt-get install samba在 Ubuntu 上创建一个共享文件夹并设置权限&#xff1a; mkdir /home/your_username/shared sudo chown nobody:nogroup /home/your_username/shared sudo chmod 0777 /home/your_username/…...

    2024/5/2 5:54:29
  4. JVM学习笔记

    文章目录 一、内存模型1. 程序计数器2. 栈3. 本地方法栈4. 堆5. 方法区方法区位置字符串常量池位置 6. 直接内存 二、虚拟机参数设置三、类的生命周期1. 加载2. 连接1&#xff09;验证2&#xff09;准备3&#xff09;解析 3. 初始化4. 卸载 四、类加载器1. 启动类加载器2. 扩展…...

    2024/5/1 13:33:02
  5. 【stm32】I2C通信协议

    【stm32】I2C通信协议 概念及原理 如果我们想要读写寄存器来控制硬件电路&#xff0c;就至少需要定义两个字节数据 一个字节是我们要读写哪个寄存器&#xff0c;也就是指定寄存器的地址 另一个字节就是这个地址下存储寄存器的内容 写入内容就是控制电路&#xff0c;读出内容就…...

    2024/5/2 2:37:26
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/2 16:16:39
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/2 9:28:15
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/2 15:04:34
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/2 9:07:46
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57