Skip to content

Commit c4ba9cb

Browse files
committed
edits when reviewing Chinese translation
Note: these changes are already reflected in the review commits for the Chinese translation and do not need to be translated.
1 parent 3251536 commit c4ba9cb

File tree

20 files changed

+97
-85
lines changed

20 files changed

+97
-85
lines changed

src/guide/best-practices/performance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Vue is designed to be performant for most common use cases without much need for
1010

1111
First, let's discuss the two major aspects of web performance:
1212

13-
- **Page Load Performance**: how fast the application shows content and becomes interactive on the initial visit. This is usually measured using web vital metrics like [Largest Contentful Paint (LCP)](https://web.dev/lcp/) and [First Input Delay](https://web.dev/fid/).
13+
- **Page Load Performance**: how fast the application shows content and becomes interactive on the initial visit. This is usually measured using web vital metrics like [Largest Contentful Paint (LCP)](https://web.dev/lcp/) and [First Input Delay (FID)](https://web.dev/fid/).
1414

1515
- **Update Performance**: how fast the application updates in response to user input. For example, how fast a list updates when the user types in a search box, or how fast the page switches when the user clicks a navigation link in a Single-Page Application (SPA).
1616

src/guide/best-practices/security.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ In any web application, allowing unsanitized, user-provided content to be execut
7272

7373
For example, services like CodePen and JSFiddle allow user-provided content to be executed, but it's in a context where this is expected and sandboxed to some extent inside iframes. In the cases when an important feature inherently requires some level of vulnerability, it's up to your team to weigh the importance of the feature against the worst-case scenarios the vulnerability enables.
7474

75-
### Injecting HTML
75+
### HTML Injection
7676

77-
As you learned earlier, Vue automatically escapes HTML content, preventing you from accidentally injecting executable HTML into your application. However, in cases where you know the HTML is safe, you can explicitly render HTML content:
77+
As you learned earlier, Vue automatically escapes HTML content, preventing you from accidentally injecting executable HTML into your application. However, **in cases where you know the HTML is safe**, you can explicitly render HTML content:
7878

7979
- Using a template:
8080

@@ -96,11 +96,11 @@ As you learned earlier, Vue automatically escapes HTML content, preventing you f
9696
<div innerHTML={this.userProvidedHtml}></div>
9797
```
9898

99-
:::tip
100-
Note that user-provided HTML can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that HTML can ever be exposed to it. Additionally, allowing users to write their own Vue templates brings similar dangers.
99+
:::warning
100+
User-provided HTML can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that HTML can ever be exposed to it. Additionally, allowing users to write their own Vue templates brings similar dangers.
101101
:::
102102

103-
### Injecting URLs
103+
### URL Injection
104104

105105
In a URL like this:
106106

@@ -110,13 +110,9 @@ In a URL like this:
110110
</a>
111111
```
112112

113-
There's a potential security issue if the URL has not been "sanitized" to prevent JavaScript execution using `javascript:`. There are libraries such as [sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) to help with this, but note:
113+
There's a potential security issue if the URL has not been "sanitized" to prevent JavaScript execution using `javascript:`. There are libraries such as [sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) to help with this, but note: if you're ever doing URL sanitization on the frontend, you already have a security issue. **User-provided URLs should always be sanitized by your backend before even being saved to a database.** Then the problem is avoided for _every_ client connecting to your API, including native mobile apps. Also note that even with sanitized URLs, Vue cannot help you guarantee that they lead to safe destinations.
114114

115-
:::tip
116-
If you're ever doing URL sanitization on the frontend, you already have a security issue. User-provided URLs should always be sanitized by your backend before even being saved to a database. Then the problem is avoided for _every_ client connecting to your API, including native mobile apps. Also note that even with sanitized URLs, Vue cannot help you guarantee that they lead to safe destinations.
117-
:::
118-
119-
### Injecting Styles
115+
### Style Injection
120116

121117
Looking at this example:
122118

@@ -151,21 +147,21 @@ To keep your users fully safe from click jacking, we recommend only allowing ful
151147
</a>
152148
```
153149

154-
### Injecting JavaScript
150+
### JavaScript Injection
155151

156152
We strongly discourage ever rendering a `<script>` element with Vue, since templates and render functions should never have side effects. However, this isn't the only way to include strings that would be evaluated as JavaScript at runtime.
157153

158154
Every HTML element has attributes with values accepting strings of JavaScript, such as `onclick`, `onfocus`, and `onmouseenter`. Binding user-provided JavaScript to any of these event attributes is a potential security risk, so should be avoided.
159155

160-
:::tip
161-
Note that user-provided JavaScript can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that JavaScript can ever be exposed to it.
156+
:::warning
157+
User-provided JavaScript can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that JavaScript can ever be exposed to it.
162158
:::
163159

164160
Sometimes we receive vulnerability reports on how it's possible to do cross-site scripting (XSS) in Vue templates. In general, we do not consider such cases to be actual vulnerabilities, because there's no practical way to protect developers from the two scenarios that would allow XSS:
165161

166162
1. The developer is explicitly asking Vue to render user-provided, unsanitized content as Vue templates. This is inherently unsafe and there's no way for Vue to know the origin.
167163

168-
2. The developer is mounting Vue to an entire HTML page which happens to contain server-rendered and user-provided content. This is fundamentally the same problem as \#1, but sometimes devs may do it without realizing. This can lead to possible vulnerabilities where the attacker provides HTML which is safe as plain HTML but unsafe as a Vue template. The best practice is to never mount Vue on nodes that may contain server-rendered and user-provided content.
164+
2. The developer is mounting Vue to an entire HTML page which happens to contain server-rendered and user-provided content. This is fundamentally the same problem as \#1, but sometimes devs may do it without realizing. This can lead to possible vulnerabilities where the attacker provides HTML which is safe as plain HTML but unsafe as a Vue template. The best practice is to **never mount Vue on nodes that may contain server-rendered and user-provided content**.
169165

170166
## Best Practices
171167

src/guide/built-ins/keep-alive.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ In the Component Basics chapter, we introduced the syntax for [Dynamic Component
1414
<component :is="activeComponent" />
1515
```
1616

17-
By default, an active component instance will be unmounted when switched away from. This will cause any changed state it holds to be lost.
17+
By default, an active component instance will be unmounted when switched away from. This will cause any changed state it holds to be lost. When this component is displayed again, a new instance will be created with only the initial state.
1818

1919
In the example below, we have two stateful components - A contains a counter, while B contains a message synced with an input via `v-model`. Try updating the state of one of them, switch away, and then switch back to it:
2020

@@ -73,6 +73,10 @@ By default, `<KeepAlive>` will cache any component instance inside. We can custo
7373

7474
The match is checked against the component's [`name`](/api/options-misc.html#name) option, so components that need to be conditionally cached by `KeepAlive` must explicitly declare a `name` option.
7575

76+
:::tip
77+
Since version 3.2.34, a single-file component using `<script setup>` will automatically infer its `name` option based on the filename, removing the need to manually declare the name.
78+
:::
79+
7680
## Max Cached Instances
7781

7882
We can limit the maximum number of component instances that can be cached via the `max` prop. When `max` is specified, `<KeepAlive>` behaves like an [LRU cache](<https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)>): if the number of cached instances is about to exceed the specified max count, the least recently accessed cached instance will be destroyed to make room for the new one.

src/guide/built-ins/transition.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ Now `MyTransition` can be imported and used just like the built-in version:
499499

500500
## Transition on Appear
501501

502-
If you also want to apply a transition on the initial render of a node, you can add the `appear` attribute:
502+
If you also want to apply a transition on the initial render of a node, you can add the `appear` prop:
503503

504504
```vue-html
505505
<Transition appear>
@@ -509,7 +509,7 @@ If you also want to apply a transition on the initial render of a node, you can
509509

510510
## Transition Between Elements
511511

512-
In addition to toggling an element with `v-if` / `v-show`, we can also transition between two elements using `v-if` / `v-else` / `v-else-if`:
512+
In addition to toggling an element with `v-if` / `v-show`, we can also transition between two elements using `v-if` / `v-else` / `v-else-if`, as long as we make sure that there is only one element being shown at any given moment:
513513

514514
```vue-html
515515
<Transition>

src/guide/components/async.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const AsyncComp = defineAsyncComponent(() => {
1818

1919
As you can see, `defineAsyncComponent` accepts a loader function that returns a Promise. The Promise's `resolve` callback should be called when you have retrieved your component definition from the server. You can also call `reject(reason)` to indicate the load has failed.
2020

21-
[ES module dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports) also returns a Promise, so most of the time we will use it in combination with `defineAsyncComponent`. Bundlers like Vite and webpack also support the syntax, so we can use it to import Vue SFCs:
21+
[ES module dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports) also returns a Promise, so most of the time we will use it in combination with `defineAsyncComponent`. Bundlers like Vite and webpack also support the syntax (and will use it as bundle split points), so we can use it to import Vue SFCs:
2222

2323
```js
2424
import { defineAsyncComponent } from 'vue'

src/guide/components/attrs.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ The final rendered DOM would be:
2929
<button class="large">click me</button>
3030
```
3131

32+
Here, `<MyButton>` did not declare `class` as an accepted prop. Therefore, `class` is treated as a fallthrough attribute and automatically added to `<MyButton>`'s root element.
33+
3234
### `class` and `style` Merging
3335

3436
If the child component's root element already has existing `class` or `style` attributes, it will be merged with the `class` and `style` values that are inherited from the parent. Suppose we change the template of `<MyButton>` in the previous example to:

src/guide/components/events.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The `.once` modifier is also supported on component event listeners:
4646
Like components and props, event names provide an automatic case transformation. Notice we emitted a camelCase event, but can listen for it using a kebab-cased listener in the parent. As with [props casing](/guide/components/props.html#prop-name-casing), we recommend using kebab-cased event listeners in templates.
4747

4848
:::tip
49-
Unlike native DOM events, component emitted events do **not** bubble. You can only listen to the events emitted by a direct child component.
49+
Unlike native DOM events, component emitted events do **not** bubble. You can only listen to the events emitted by a direct child component. If there is a need to communicate between sibling or deeply nested components, use an external event bus or a [global state management solution](/guide/scaling-up/state-management.html).
5050
:::
5151

5252
## Event Arguments
@@ -203,7 +203,7 @@ See also: [Typing Component Emits](/guide/typescript/options-api.html#typing-com
203203

204204
</div>
205205

206-
Although optional, it is recommended to define all emitted events in order to better document how a component should work. It also allows Vue to exclude known listeners from [fallthrough attributes](/guide/components/attrs.html#v-on-listener-inheritance).
206+
Although optional, it is recommended to define all emitted events in order to better document how a component should work. It also allows Vue to exclude known listeners from [fallthrough attributes](/guide/components/attrs.html#v-on-listener-inheritance), avoiding edge cases caused by DOM events manually dispatched by 3rd party code.
207207

208208
:::tip
209209
If a native event (e.g., `click`) is defined in the `emits` option, the listener will now only listen to component-emitted `click` events and no longer respond to native `click` events.
@@ -271,13 +271,13 @@ export default {
271271

272272
## Usage with `v-model`
273273

274-
Custom events can also be used to create custom inputs that work with `v-model`. Remember that:
274+
Custom events can also be used to create custom inputs that work with `v-model`. Let's revisit how `v-model` is used on a native element:
275275

276276
```vue-html
277277
<input v-model="searchText" />
278278
```
279279

280-
does the same thing as:
280+
Under the hood, the template compiler expands `v-model` to the more verbose equivalent for us. So the above code does the same as the following:
281281

282282
```vue-html
283283
<input
@@ -286,7 +286,7 @@ does the same thing as:
286286
/>
287287
```
288288

289-
When used on a component, `v-model` instead does this:
289+
When used on a component, `v-model` instead expands to this:
290290

291291
```vue-html
292292
<CustomInput
@@ -295,10 +295,10 @@ When used on a component, `v-model` instead does this:
295295
/>
296296
```
297297

298-
For this to actually work though, the `<input>` inside the component must:
298+
For this to actually work though, the `<CustomInput>` component must do two things:
299299

300-
- Bind the `value` attribute to the `modelValue` prop
301-
- On `input`, emit an `update:modelValue` event with the new value
300+
1. Bind the `value` attribute of a native `<input>` element to the `modelValue` prop
301+
2. When a native `input` event is triggered, emit an `update:modelValue` custom event with the new value
302302

303303
Here's that in action:
304304

@@ -544,7 +544,7 @@ export default {
544544

545545
### Handling `v-model` modifiers
546546

547-
When we were learning about form input bindings, we saw that `v-model` has [built-in modifiers](/guide/essentials/forms.html#modifiers) - `.trim`, `.number` and `.lazy`. In some cases, however, you might also want to add your own custom modifiers.
547+
When we were learning about form input bindings, we saw that `v-model` has [built-in modifiers](/guide/essentials/forms.html#modifiers) - `.trim`, `.number` and `.lazy`. In some cases, you might also want the `v-model` on your custom input component to support custom modifiers.
548548

549549
Let's create an example custom modifier, `capitalize`, that capitalizes the first letter of the string provided by the `v-model` binding:
550550

src/guide/components/props.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ Additional details:
483483
- All props are optional by default, unless `required: true` is specified.
484484

485485
- An absent optional prop other than `Boolean` will have `undefined` value.
486-
486+
487487
- The `Boolean` absent props will be cast to `false`. You should set a `default` value for it in order to get desired behavior.
488488

489489
- If a `default` value is specified, it will be used if the resolved prop value is `undefined` - this includes both when the prop is absent, or an explicit `undefined` value is passed.
@@ -492,7 +492,7 @@ When prop validation fails, Vue will produce a console warning (if using the dev
492492

493493
<div class="composition-api">
494494

495-
If using [Type-based props declarations](/api/sfc-script-setup.html#typescript-only-features), Vue will try its best to compile the type annotations into equivalent runtime prop declarations. For example, `defineProps<{ msg: string }>` will be compiled into `{ msg: { type: String, required: true }}`.
495+
If using [Type-based props declarations](/api/sfc-script-setup.html#typescript-only-features) <sup class="vt-badge ts" />, Vue will try its best to compile the type annotations into equivalent runtime prop declarations. For example, `defineProps<{ msg: string }>` will be compiled into `{ msg: { type: String, required: true }}`.
496496

497497
</div>
498498
<div class="options-api">
@@ -550,7 +550,7 @@ export default {
550550

551551
</div>
552552

553-
to validate that the value of the `author` prop was created with `new Person`.
553+
Vue will use `instanceof Person` to validate whether the value of the `author` prop is indeed an instance of the `Person` class.
554554

555555
## Boolean Casting
556556

src/guide/components/slots.md

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ The `<slot>` element is a **slot outlet** that indicates where the parent-provid
3333
And the final rendered DOM:
3434

3535
```html
36-
<button class="fancy-btn">
37-
Click me!
38-
</button>
36+
<button class="fancy-btn">Click me!</button>
3937
```
4038

4139
<div class="composition-api">
@@ -59,11 +57,9 @@ FancyButton('Click me!')
5957

6058
// FancyButton renders slot content in its own template
6159
function FancyButton(slotContent) {
62-
return (
63-
`<button class="fancy-btn">
60+
return `<button class="fancy-btn">
6461
${slotContent}
6562
</button>`
66-
)
6763
}
6864
```
6965

@@ -102,9 +98,9 @@ Slot content has access to the data scope of the parent component, because it is
10298

10399
Here both <span v-pre>`{{ message }}`</span> interpolations will render the same content.
104100

105-
Slot content does **not** have access to the child component's data. As a rule, remember that:
101+
Slot content does **not** have access to the child component's data. Expressions in Vue templates can only access the scope it is defined in, consistent with JavaScript's lexical scoping. In other words:
106102

107-
> Everything in the parent template is compiled in parent scope; everything in the child template is compiled in the child scope.
103+
> Expressions in the parent template only have access to the parent scope; expressions in the child template only have access to the child scope.
108104
109105
## Fallback Content
110106

@@ -292,13 +288,11 @@ BaseLayout({
292288

293289
// <BaseLayout> renders them in different places
294290
function BaseLayout(slots) {
295-
return (
296-
`<div class="container">
291+
return `<div class="container">
297292
<header>${slots.header}</header>
298293
<main>${slots.default}</main>
299294
<footer>${slots.footer}</footer>
300295
</div>`
301-
)
302296
}
303297
```
304298

@@ -373,12 +367,10 @@ MyComponent({
373367

374368
function MyComponent(slots) {
375369
const greetingMessage = 'hello'
376-
return (
377-
`<div>${
378-
// call the slot function with props!
379-
slots.default({ text: greetingMessage, count: 1 })
380-
}</div>`
381-
)
370+
return `<div>${
371+
// call the slot function with props!
372+
slots.default({ text: greetingMessage, count: 1 })
373+
}</div>`
382374
}
383375
```
384376

@@ -420,7 +412,6 @@ Passing props to a named slot:
420412

421413
Note the `name` of a slot won't be included in the props because it is reserved - so the resulting `headerProps` would be `{ message: 'hello' }`.
422414

423-
424415
### Fancy List Example
425416

426417
You may be wondering what would be a good use case for scoped slots. Here's an example: imagine a `<FancyList>` component that renders a list of items - it may encapsulate the logic for loading remote data, using the data to display a list, or even advanced features like pagination or infinite scrolling. However, we want it to be flexible with how each item looks and leave the styling of each item to the parent component consuming it. So the desired usage may look like this:

0 commit comments

Comments
 (0)