mirror of https://github.com/vuejs/core.git
style: format html&markdown files (#11531)
This commit is contained in:
parent
7c75cc3988
commit
8a99f903db
|
@ -74,9 +74,9 @@ The scope could be anything specifying the place of the commit change. For examp
|
||||||
|
|
||||||
The subject contains a succinct description of the change:
|
The subject contains a succinct description of the change:
|
||||||
|
|
||||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
- use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
* don't capitalize the first letter
|
- don't capitalize the first letter
|
||||||
* no dot (.) at the end
|
- no dot (.) at the end
|
||||||
|
|
||||||
### Body
|
### Body
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
|
||||||
|
|
||||||
Another aspect of it is that large scale stylistic changes result in massive diffs that touch multiple files, adding noise to the git history and makes tracing behavior changes across commits more cumbersome.
|
Another aspect of it is that large scale stylistic changes result in massive diffs that touch multiple files, adding noise to the git history and makes tracing behavior changes across commits more cumbersome.
|
||||||
|
|
||||||
|
|
||||||
### Pull Request Checklist
|
### Pull Request Checklist
|
||||||
|
|
||||||
- Vue core has two primary work branches: `main` and `minor`.
|
- Vue core has two primary work branches: `main` and `minor`.
|
||||||
|
|
|
@ -80,6 +80,7 @@ Depending on the type of the PR, different considerations need to be taken into
|
||||||
- Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.
|
- Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.
|
||||||
|
|
||||||
- Performance
|
- Performance
|
||||||
|
|
||||||
- Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.
|
- Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.
|
||||||
|
|
||||||
- Potential Breakage
|
- Potential Breakage
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
dist
|
dist
|
||||||
*.md
|
|
||||||
*.html
|
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
CHANGELOG*.md
|
||||||
|
|
|
@ -13,7 +13,7 @@ const { render, createApp } = createRenderer({
|
||||||
patchProp,
|
patchProp,
|
||||||
insert,
|
insert,
|
||||||
remove,
|
remove,
|
||||||
createElement
|
createElement,
|
||||||
// ...
|
// ...
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { h, createApp } from '@vue/runtime-dom'
|
||||||
const RootComponent = {
|
const RootComponent = {
|
||||||
render() {
|
render() {
|
||||||
return h('div', 'hello world')
|
return h('div', 'hello world')
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
createApp(RootComponent).mount('#app')
|
createApp(RootComponent).mount('#app')
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
```ts
|
```ts
|
||||||
function renderToString(
|
function renderToString(
|
||||||
input: App | VNode,
|
input: App | VNode,
|
||||||
context?: SSRContext
|
context?: SSRContext,
|
||||||
): Promise<string>
|
): Promise<string>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const { renderToString } = require('@vue/server-renderer')
|
||||||
|
|
||||||
const app = createSSRApp({
|
const app = createSSRApp({
|
||||||
data: () => ({ msg: 'hello' }),
|
data: () => ({ msg: 'hello' }),
|
||||||
template: `<div>{{ msg }}</div>`
|
template: `<div>{{ msg }}</div>`,
|
||||||
})
|
})
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
|
@ -74,7 +74,7 @@ Render and pipe to an existing [Node.js Writable stream](https://nodejs.org/api/
|
||||||
function pipeToNodeWritable(
|
function pipeToNodeWritable(
|
||||||
input: App | VNode,
|
input: App | VNode,
|
||||||
context: SSRContext = {},
|
context: SSRContext = {},
|
||||||
writable: Writable
|
writable: Writable,
|
||||||
): void
|
): void
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ Renders input as a [Web ReadableStream](https://developer.mozilla.org/en-US/docs
|
||||||
```ts
|
```ts
|
||||||
function renderToWebStream(
|
function renderToWebStream(
|
||||||
input: App | VNode,
|
input: App | VNode,
|
||||||
context?: SSRContext
|
context?: SSRContext,
|
||||||
): ReadableStream
|
): ReadableStream
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ Render and pipe to an existing [Web WritableStream](https://developer.mozilla.or
|
||||||
function pipeToWebWritable(
|
function pipeToWebWritable(
|
||||||
input: App | VNode,
|
input: App | VNode,
|
||||||
context: SSRContext = {},
|
context: SSRContext = {},
|
||||||
writable: WritableStream
|
writable: WritableStream,
|
||||||
): void
|
): void
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ Renders input in streaming mode using a simple readable interface.
|
||||||
function renderToSimpleStream(
|
function renderToSimpleStream(
|
||||||
input: App | VNode,
|
input: App | VNode,
|
||||||
context: SSRContext,
|
context: SSRContext,
|
||||||
options: SimpleReadable
|
options: SimpleReadable,
|
||||||
): SimpleReadable
|
): SimpleReadable
|
||||||
|
|
||||||
interface SimpleReadable {
|
interface SimpleReadable {
|
||||||
|
@ -172,7 +172,7 @@ renderToSimpleStream(
|
||||||
},
|
},
|
||||||
destroy(err) {
|
destroy(err) {
|
||||||
// error encountered
|
// error encountered
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
@ -7,10 +7,13 @@
|
||||||
<link rel="icon" type="image/svg" href="/logo.svg" />
|
<link rel="icon" type="image/svg" href="/logo.svg" />
|
||||||
<title>Vue SFC Playground</title>
|
<title>Vue SFC Playground</title>
|
||||||
<script>
|
<script>
|
||||||
const savedPreferDark = localStorage.getItem('vue-sfc-playground-prefer-dark')
|
const savedPreferDark = localStorage.getItem(
|
||||||
|
'vue-sfc-playground-prefer-dark',
|
||||||
|
)
|
||||||
if (
|
if (
|
||||||
savedPreferDark === 'true' ||
|
savedPreferDark === 'true' ||
|
||||||
(!savedPreferDark && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
(!savedPreferDark &&
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||||
) {
|
) {
|
||||||
document.documentElement.classList.add('dark')
|
document.documentElement.classList.add('dark')
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<title>Vue Template Explorer</title>
|
<title>Vue Template Explorer</title>
|
||||||
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://unpkg.com/monaco-editor@0.20.0/min/vs/editor/editor.main.css">
|
<link
|
||||||
<link rel="stylesheet" href="./style.css">
|
rel="stylesheet"
|
||||||
|
data-name="vs/editor/editor.main"
|
||||||
|
href="https://unpkg.com/monaco-editor@0.20.0/min/vs/editor/editor.main.css"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="./style.css" />
|
||||||
|
|
||||||
<div id="header"></div>
|
<div id="header"></div>
|
||||||
<div id="source" class="editor"></div>
|
<div id="source" class="editor"></div>
|
||||||
|
@ -10,8 +14,8 @@
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
paths: {
|
paths: {
|
||||||
'vs': 'https://unpkg.com/monaco-editor@0.20.0/min/vs'
|
vs: 'https://unpkg.com/monaco-editor@0.20.0/min/vs',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<script src="./dist/template-explorer.global.js"></script>
|
<script src="./dist/template-explorer.global.js"></script>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<title>Vue Template Explorer</title>
|
<title>Vue Template Explorer</title>
|
||||||
<link rel="stylesheet" data-name="vs/editor/editor.main" href="./node_modules/monaco-editor/min/vs/editor/editor.main.css">
|
<link
|
||||||
<link rel="stylesheet" href="./style.css">
|
rel="stylesheet"
|
||||||
|
data-name="vs/editor/editor.main"
|
||||||
|
href="./node_modules/monaco-editor/min/vs/editor/editor.main.css"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="./style.css" />
|
||||||
|
|
||||||
<div id="header"></div>
|
<div id="header"></div>
|
||||||
<div id="source" class="editor"></div>
|
<div id="source" class="editor"></div>
|
||||||
|
@ -10,8 +14,8 @@
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
paths: {
|
paths: {
|
||||||
'vs': './node_modules/monaco-editor/min/vs'
|
vs: './node_modules/monaco-editor/min/vs',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<script src="./dist/template-explorer.global.js"></script>
|
<script src="./dist/template-explorer.global.js"></script>
|
||||||
|
|
|
@ -84,12 +84,12 @@ The following workflow walks through the steps of migrating an actual Vue 2 app
|
||||||
...options,
|
...options,
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
compatConfig: {
|
compatConfig: {
|
||||||
MODE: 2
|
MODE: 2,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ The following workflow walks through the steps of migrating an actual Vue 2 app
|
||||||
module.exports = {
|
module.exports = {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
vue: '@vue/compat'
|
vue: '@vue/compat',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
@ -114,13 +114,13 @@ The following workflow walks through the steps of migrating an actual Vue 2 app
|
||||||
options: {
|
options: {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
compatConfig: {
|
compatConfig: {
|
||||||
MODE: 2
|
MODE: 2,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -134,20 +134,20 @@ The following workflow walks through the steps of migrating an actual Vue 2 app
|
||||||
export default {
|
export default {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
vue: '@vue/compat'
|
vue: '@vue/compat',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue({
|
vue({
|
||||||
template: {
|
template: {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
compatConfig: {
|
compatConfig: {
|
||||||
MODE: 2
|
MODE: 2,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ import { configureCompat } from 'vue'
|
||||||
// disable compat for certain features
|
// disable compat for certain features
|
||||||
configureCompat({
|
configureCompat({
|
||||||
FEATURE_ID_A: false,
|
FEATURE_ID_A: false,
|
||||||
FEATURE_ID_B: false
|
FEATURE_ID_B: false,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ import { configureCompat } from 'vue'
|
||||||
configureCompat({
|
configureCompat({
|
||||||
MODE: 3,
|
MODE: 3,
|
||||||
FEATURE_ID_A: true,
|
FEATURE_ID_A: true,
|
||||||
FEATURE_ID_B: true
|
FEATURE_ID_B: true,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -233,8 +233,8 @@ A component can use the `compatConfig` option, which expects the same options as
|
||||||
export default {
|
export default {
|
||||||
compatConfig: {
|
compatConfig: {
|
||||||
MODE: 3, // opt-in to Vue 3 behavior for this component only
|
MODE: 3, // opt-in to Vue 3 behavior for this component only
|
||||||
FEATURE_ID_A: true // features can also be toggled at component level
|
FEATURE_ID_A: true, // features can also be toggled at component level
|
||||||
}
|
},
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -257,18 +257,18 @@ Features that start with `COMPILER_` are compiler-specific: if you are using the
|
||||||
> Should be fixed upfront or will likely lead to errors
|
> Should be fixed upfront or will likely lead to errors
|
||||||
|
|
||||||
| ID | Type | Description | Docs |
|
| ID | Type | Description | Docs |
|
||||||
| ------------------------------------- | ---- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
| ------------------------------------- | ---- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||||
| GLOBAL_MOUNT_CONTAINER | ⨂ | Mounted application does not replace the element it's mounted to | [link](https://v3-migration.vuejs.org/breaking-changes/mount-changes.html) |
|
| GLOBAL_MOUNT_CONTAINER | ⨂ | Mounted application does not replace the element it's mounted to | [link](https://v3-migration.vuejs.org/breaking-changes/mount-changes.html) |
|
||||||
| CONFIG_DEVTOOLS | ⨂ | production devtools is now a build-time flag | [link](https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags) |
|
| CONFIG_DEVTOOLS | ⨂ | production devtools is now a build-time flag | [link](https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags) |
|
||||||
| COMPILER_V_IF_V_FOR_PRECEDENCE | ⨂ | `v-if` and `v-for` precedence when used on the same element has changed | [link](https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html) |
|
| COMPILER_V_IF_V_FOR_PRECEDENCE | ⨂ | `v-if` and `v-for` precedence when used on the same element has changed | [link](https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html) |
|
||||||
| COMPILER_V_IF_SAME_KEY | ⨂ | `v-if` branches can no longer have the same key | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#on-conditional-branches) |
|
| COMPILER_V_IF_SAME_KEY | ⨂ | `v-if` branches can no longer have the same key | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#on-conditional-branches) |
|
||||||
| COMPILER_V_FOR_TEMPLATE_KEY_PLACEMENT | ⨂ | `<template v-for>` key should now be placed on `<template>` | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#with-template-v-for) |
|
| COMPILER_V_FOR_TEMPLATE_KEY_PLACEMENT | ⨂ | `<template v-for>` key should now be placed on `<template>` | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#with-template-v-for) |
|
||||||
| COMPILER_SFC_FUNCTIONAL | ⨂ | `<template functional>` is no longer supported in SFCs | [link](https://v3-migration.vuejs.org/breaking-changes/functional-components.html#single-file-components-sfcs) | | |
|
| COMPILER_SFC_FUNCTIONAL | ⨂ | `<template functional>` is no longer supported in SFCs | [link](https://v3-migration.vuejs.org/breaking-changes/functional-components.html#single-file-components-sfcs) |
|
||||||
|
|
||||||
### Partially Compatible with Caveats
|
### Partially Compatible with Caveats
|
||||||
|
|
||||||
| ID | Type | Description | Docs |
|
| ID | Type | Description | Docs |
|
||||||
| ------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
| ------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| CONFIG_IGNORED_ELEMENTS | ◐ | `config.ignoredElements` is now `config.compilerOptions.isCustomElement` (only in browser compiler build). If using build setup, `isCustomElement` must be passed via build configuration. | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-ignoredelements-is-now-config-iscustomelement) |
|
| CONFIG_IGNORED_ELEMENTS | ◐ | `config.ignoredElements` is now `config.compilerOptions.isCustomElement` (only in browser compiler build). If using build setup, `isCustomElement` must be passed via build configuration. | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-ignoredelements-is-now-config-iscustomelement) |
|
||||||
| COMPILER_INLINE_TEMPLATE | ◐ | `inline-template` removed (compat only supported in browser compiler build) | [link](https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html) |
|
| COMPILER_INLINE_TEMPLATE | ◐ | `inline-template` removed (compat only supported in browser compiler build) | [link](https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html) |
|
||||||
| PROPS_DEFAULT_THIS | ◐ | props default factory no longer have access to `this` (in compat mode, `this` is not a real instance - it only exposes props, `$options` and injections) | [link](https://v3-migration.vuejs.org/breaking-changes/props-default-this.html) |
|
| PROPS_DEFAULT_THIS | ◐ | props default factory no longer have access to `this` (in compat mode, `this` is not a real instance - it only exposes props, `$options` and injections) | [link](https://v3-migration.vuejs.org/breaking-changes/props-default-this.html) |
|
||||||
|
@ -280,13 +280,13 @@ Features that start with `COMPILER_` are compiler-specific: if you are using the
|
||||||
### Compat only (no warning)
|
### Compat only (no warning)
|
||||||
|
|
||||||
| ID | Type | Description | Docs |
|
| ID | Type | Description | Docs |
|
||||||
| ------------------ | ---- | ------------------------------------- | ---------------------------------------- |
|
| ------------------ | ---- | -------------------------------------- | ----------------------------------------------------------------------- |
|
||||||
| TRANSITION_CLASSES | ⭘ | Transition enter/leave classes changed | [link](https://v3-migration.vuejs.org/breaking-changes/transition.html) |
|
| TRANSITION_CLASSES | ⭘ | Transition enter/leave classes changed | [link](https://v3-migration.vuejs.org/breaking-changes/transition.html) |
|
||||||
|
|
||||||
### Fully Compatible
|
### Fully Compatible
|
||||||
|
|
||||||
| ID | Type | Description | Docs |
|
| ID | Type | Description | Docs |
|
||||||
| ---------------------------- | ---- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
| ---------------------------- | ---- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| GLOBAL_MOUNT | ✔ | new Vue() -> createApp | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#mounting-app-instance) |
|
| GLOBAL_MOUNT | ✔ | new Vue() -> createApp | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#mounting-app-instance) |
|
||||||
| GLOBAL_EXTEND | ✔ | Vue.extend removed (use `defineComponent` or `extends` option) | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-extend-replaced-by-definecomponent) |
|
| GLOBAL_EXTEND | ✔ | Vue.extend removed (use `defineComponent` or `extends` option) | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-extend-replaced-by-definecomponent) |
|
||||||
| GLOBAL_PROTOTYPE | ✔ | `Vue.prototype` -> `app.config.globalProperties` | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-prototype-replaced-by-config-globalproperties) |
|
| GLOBAL_PROTOTYPE | ✔ | `Vue.prototype` -> `app.config.globalProperties` | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-prototype-replaced-by-config-globalproperties) |
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
### From CDN or without a Bundler
|
### From CDN or without a Bundler
|
||||||
|
|
||||||
- **`vue(.runtime).global(.prod).js`**:
|
- **`vue(.runtime).global(.prod).js`**:
|
||||||
|
|
||||||
- For direct use via `<script src="...">` in the browser. Exposes the `Vue` global.
|
- For direct use via `<script src="...">` in the browser. Exposes the `Vue` global.
|
||||||
- Note that global builds are not [UMD](https://github.com/umdjs/umd) builds. They are built as [IIFEs](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) and is only meant for direct use via `<script src="...">`.
|
- Note that global builds are not [UMD](https://github.com/umdjs/umd) builds. They are built as [IIFEs](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) and is only meant for direct use via `<script src="...">`.
|
||||||
- In-browser template compilation:
|
- In-browser template compilation:
|
||||||
|
@ -38,10 +39,12 @@
|
||||||
`esm-bundler` builds of Vue expose global feature flags that can be overwritten at compile time:
|
`esm-bundler` builds of Vue expose global feature flags that can be overwritten at compile time:
|
||||||
|
|
||||||
- `__VUE_OPTIONS_API__`
|
- `__VUE_OPTIONS_API__`
|
||||||
|
|
||||||
- Default: `true`
|
- Default: `true`
|
||||||
- Enable / disable Options API support
|
- Enable / disable Options API support
|
||||||
|
|
||||||
- `__VUE_PROD_DEVTOOLS__`
|
- `__VUE_PROD_DEVTOOLS__`
|
||||||
|
|
||||||
- Default: `false`
|
- Default: `false`
|
||||||
- Enable / disable devtools support in production
|
- Enable / disable devtools support in production
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
-webkit-transition: -webkit-transform 50ms ease;
|
-webkit-transition: -webkit-transform 50ms ease;
|
||||||
transition: transform 50ms ease;
|
transition: transform 50ms ease;
|
||||||
}
|
}
|
||||||
.v-appear, .v-enter, .v-leave-active,
|
.v-appear,
|
||||||
.test-appear, .test-enter, .test-leave-active,
|
.v-enter,
|
||||||
.hello, .bye.active,
|
.v-leave-active,
|
||||||
|
.test-appear,
|
||||||
|
.test-enter,
|
||||||
|
.test-leave-active,
|
||||||
|
.hello,
|
||||||
|
.bye.active,
|
||||||
.changed-enter {
|
.changed-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
@ -33,19 +38,35 @@
|
||||||
-webkit-animation: test-leave 100ms;
|
-webkit-animation: test-leave 100ms;
|
||||||
}
|
}
|
||||||
@keyframes test-enter {
|
@keyframes test-enter {
|
||||||
from { opacity: 0 }
|
from {
|
||||||
to { opacity: 1 }
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@-webkit-keyframes test-enter {
|
@-webkit-keyframes test-enter {
|
||||||
from { opacity: 0 }
|
from {
|
||||||
to { opacity: 1 }
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@keyframes test-leave {
|
@keyframes test-leave {
|
||||||
from { opacity: 1 }
|
from {
|
||||||
to { opacity: 0 }
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@-webkit-keyframes test-leave {
|
@-webkit-keyframes test-leave {
|
||||||
from { opacity: 1 }
|
from {
|
||||||
to { opacity: 0 }
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,19 +3,28 @@
|
||||||
<div id="demo">
|
<div id="demo">
|
||||||
<h1>Latest Vue.js Commits</h1>
|
<h1>Latest Vue.js Commits</h1>
|
||||||
<template v-for="branch in branches">
|
<template v-for="branch in branches">
|
||||||
<input type="radio"
|
<input
|
||||||
|
type="radio"
|
||||||
:id="branch"
|
:id="branch"
|
||||||
:value="branch"
|
:value="branch"
|
||||||
name="branch"
|
name="branch"
|
||||||
v-model="currentBranch">
|
v-model="currentBranch"
|
||||||
|
/>
|
||||||
<label :for="branch">{{ branch }}</label>
|
<label :for="branch">{{ branch }}</label>
|
||||||
</template>
|
</template>
|
||||||
<p>vuejs/core@{{ currentBranch }}</p>
|
<p>vuejs/core@{{ currentBranch }}</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="{ html_url, sha, author, commit } in commits">
|
<li v-for="{ html_url, sha, author, commit } in commits">
|
||||||
<a :href="html_url" target="_blank" class="commit">{{ sha.slice(0, 7) }}</a>
|
<a :href="html_url" target="_blank" class="commit"
|
||||||
- <span class="message">{{ truncate(commit.message) }}</span><br>
|
>{{ sha.slice(0, 7) }}</a
|
||||||
by <span class="author"><a :href="author.html_url" target="_blank">{{ commit.author.name }}</a></span>
|
>
|
||||||
|
- <span class="message">{{ truncate(commit.message) }}</span><br />
|
||||||
|
by
|
||||||
|
<span class="author"
|
||||||
|
><a :href="author.html_url" target="_blank"
|
||||||
|
>{{ commit.author.name }}</a
|
||||||
|
></span
|
||||||
|
>
|
||||||
at <span class="date">{{ formatDate(commit.author.date) }}</span>
|
at <span class="date">{{ formatDate(commit.author.date) }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -28,7 +37,7 @@ Vue.createApp({
|
||||||
data: () => ({
|
data: () => ({
|
||||||
branches: ['main', 'v2-compat'],
|
branches: ['main', 'v2-compat'],
|
||||||
currentBranch: 'main',
|
currentBranch: 'main',
|
||||||
commits: null
|
commits: null,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
|
@ -36,7 +45,7 @@ Vue.createApp({
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
currentBranch: 'fetchData'
|
currentBranch: 'fetchData',
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -53,8 +62,8 @@ Vue.createApp({
|
||||||
},
|
},
|
||||||
formatDate(v) {
|
formatDate(v) {
|
||||||
return v.replace(/T|Z/g, ' ')
|
return v.replace(/T|Z/g, ' ')
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -70,7 +79,8 @@ Vue.createApp({
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.author, .date {
|
.author,
|
||||||
|
.date {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,12 +31,12 @@ const DemoGrid = {
|
||||||
props: {
|
props: {
|
||||||
data: Array,
|
data: Array,
|
||||||
columns: Array,
|
columns: Array,
|
||||||
filterKey: String
|
filterKey: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sortKey: '',
|
sortKey: '',
|
||||||
sortOrders: this.columns.reduce((o, key) => (o[key] = 1, o), {})
|
sortOrders: this.columns.reduce((o, key) => ((o[key] = 1), o), {}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -60,7 +60,7 @@ const DemoGrid = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sortBy(key) {
|
sortBy(key) {
|
||||||
|
@ -69,27 +69,22 @@ const DemoGrid = {
|
||||||
},
|
},
|
||||||
capitalize(str) {
|
capitalize(str) {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- App template (in DOM) -->
|
<!-- App template (in DOM) -->
|
||||||
<div id="demo">
|
<div id="demo">
|
||||||
<form id="search">
|
<form id="search">Search <input name="query" v-model="searchQuery" /></form>
|
||||||
Search <input name="query" v-model="searchQuery">
|
<demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery">
|
||||||
</form>
|
|
||||||
<demo-grid
|
|
||||||
:data="gridData"
|
|
||||||
:columns="gridColumns"
|
|
||||||
:filter-key="searchQuery">
|
|
||||||
</demo-grid>
|
</demo-grid>
|
||||||
</div>
|
</div>
|
||||||
<!-- App script -->
|
<!-- App script -->
|
||||||
<script>
|
<script>
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
DemoGrid
|
DemoGrid,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
|
@ -98,15 +93,18 @@ Vue.createApp({
|
||||||
{ name: 'Chuck Norris', power: Infinity },
|
{ name: 'Chuck Norris', power: Infinity },
|
||||||
{ name: 'Bruce Lee', power: 9000 },
|
{ name: 'Bruce Lee', power: 9000 },
|
||||||
{ name: 'Jackie Chan', power: 7000 },
|
{ name: 'Jackie Chan', power: 7000 },
|
||||||
{ name: 'Jet Li', power: 8000 }
|
{ name: 'Jet Li', power: 8000 },
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,8 @@ td {
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,30 +10,33 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
data: () => ({
|
data: () => ({
|
||||||
input: '# hello'
|
input: '# hello',
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
compiledMarkdown() {
|
compiledMarkdown() {
|
||||||
return marked.marked(this.input, { sanitize: true })
|
return marked.marked(this.input, { sanitize: true })
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
update: _.debounce(function (e) {
|
update: _.debounce(function (e) {
|
||||||
this.input = e.target.value
|
this.input = e.target.value
|
||||||
}, 50)
|
}, 50),
|
||||||
}
|
},
|
||||||
}).mount('#editor')
|
}).mount('#editor')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
html, body, #editor {
|
html,
|
||||||
|
body,
|
||||||
|
#editor {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea, #editor div {
|
textarea,
|
||||||
|
#editor div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
function valueToPoint(value, index, total) {
|
function valueToPoint(value, index, total) {
|
||||||
var x = 0
|
var x = 0
|
||||||
var y = -value * 0.8
|
var y = -value * 0.8
|
||||||
var angle = Math.PI * 2 / total * index
|
var angle = ((Math.PI * 2) / total) * index
|
||||||
var cos = Math.cos(angle)
|
var cos = Math.cos(angle)
|
||||||
var sin = Math.sin(angle)
|
var sin = Math.sin(angle)
|
||||||
var tx = x * cos - y * sin + 100
|
var tx = x * cos - y * sin + 100
|
||||||
var ty = x * sin + y * cos + 100
|
var ty = x * sin + y * cos + 100
|
||||||
return {
|
return {
|
||||||
x: tx,
|
x: tx,
|
||||||
y: ty
|
y: ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,17 +20,13 @@ const AxisLabel = {
|
||||||
props: {
|
props: {
|
||||||
stat: Object,
|
stat: Object,
|
||||||
index: Number,
|
index: Number,
|
||||||
total: Number
|
total: Number,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
point: function () {
|
point: function () {
|
||||||
return valueToPoint(
|
return valueToPoint(+this.stat.value + 10, this.index, this.total)
|
||||||
+this.stat.value + 10,
|
},
|
||||||
this.index,
|
},
|
||||||
this.total
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -56,15 +52,17 @@ const Polygraph = {
|
||||||
// a computed property for the polygon's points
|
// a computed property for the polygon's points
|
||||||
points() {
|
points() {
|
||||||
const total = this.stats.length
|
const total = this.stats.length
|
||||||
return this.stats.map((stat, i) => {
|
return this.stats
|
||||||
|
.map((stat, i) => {
|
||||||
const point = valueToPoint(stat.value, i, total)
|
const point = valueToPoint(stat.value, i, total)
|
||||||
return point.x + ',' + point.y
|
return point.x + ',' + point.y
|
||||||
}).join(' ')
|
})
|
||||||
}
|
.join(' ')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
AxisLabel
|
AxisLabel,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -77,12 +75,12 @@ const Polygraph = {
|
||||||
<!-- controls -->
|
<!-- controls -->
|
||||||
<div v-for="stat in stats">
|
<div v-for="stat in stats">
|
||||||
<label>{{stat.label}}</label>
|
<label>{{stat.label}}</label>
|
||||||
<input type="range" v-model="stat.value" min="0" max="100">
|
<input type="range" v-model="stat.value" min="0" max="100" />
|
||||||
<span>{{stat.value}}</span>
|
<span>{{stat.value}}</span>
|
||||||
<button @click="remove(stat)" class="remove">X</button>
|
<button @click="remove(stat)" class="remove">X</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="add">
|
<form id="add">
|
||||||
<input name="newlabel" v-model="newLabel">
|
<input name="newlabel" v-model="newLabel" />
|
||||||
<button @click="add">Add a Stat</button>
|
<button @click="add">Add a Stat</button>
|
||||||
</form>
|
</form>
|
||||||
<pre id="raw">{{ stats }}</pre>
|
<pre id="raw">{{ stats }}</pre>
|
||||||
|
@ -95,16 +93,16 @@ const globalStats = [
|
||||||
{ label: 'C', value: 100 },
|
{ label: 'C', value: 100 },
|
||||||
{ label: 'D', value: 100 },
|
{ label: 'D', value: 100 },
|
||||||
{ label: 'E', value: 100 },
|
{ label: 'E', value: 100 },
|
||||||
{ label: 'F', value: 100 }
|
{ label: 'F', value: 100 },
|
||||||
]
|
]
|
||||||
|
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
Polygraph
|
Polygraph,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
newLabel: '',
|
newLabel: '',
|
||||||
stats: globalStats
|
stats: globalStats,
|
||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
add(e) {
|
add(e) {
|
||||||
|
@ -112,7 +110,7 @@ Vue.createApp({
|
||||||
if (!this.newLabel) return
|
if (!this.newLabel) return
|
||||||
this.stats.push({
|
this.stats.push({
|
||||||
label: this.newLabel,
|
label: this.newLabel,
|
||||||
value: 100
|
value: 100,
|
||||||
})
|
})
|
||||||
this.newLabel = ''
|
this.newLabel = ''
|
||||||
},
|
},
|
||||||
|
@ -120,21 +118,24 @@ Vue.createApp({
|
||||||
if (this.stats.length > 3) {
|
if (this.stats.length > 3) {
|
||||||
this.stats.splice(this.stats.indexOf(stat), 1)
|
this.stats.splice(this.stats.indexOf(stat), 1)
|
||||||
} else {
|
} else {
|
||||||
alert('Can\'t delete more!')
|
alert("Can't delete more!")
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
polygon {
|
polygon {
|
||||||
fill: #42b983;
|
fill: #42b983;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle {
|
circle {
|
||||||
|
@ -143,7 +144,10 @@ circle {
|
||||||
}
|
}
|
||||||
|
|
||||||
text {
|
text {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
fill: #666;
|
fill: #666;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +1,81 @@
|
||||||
<script src="../../dist/vue.global.js"></script>
|
<script src="../../dist/vue.global.js"></script>
|
||||||
<link rel="stylesheet" href="../../../../node_modules/todomvc-app-css/index.css">
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="../../../../node_modules/todomvc-app-css/index.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<section class="todoapp">
|
<section class="todoapp">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<h1>todos</h1>
|
<h1>todos</h1>
|
||||||
<input class="new-todo"
|
<input
|
||||||
autofocus autocomplete="off"
|
class="new-todo"
|
||||||
|
autofocus
|
||||||
|
autocomplete="off"
|
||||||
placeholder="What needs to be done?"
|
placeholder="What needs to be done?"
|
||||||
v-model="newTodo"
|
v-model="newTodo"
|
||||||
@keyup.enter="addTodo">
|
@keyup.enter="addTodo"
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
<section class="main" v-show="todos.length">
|
<section class="main" v-show="todos.length">
|
||||||
<input id="toggle-all" class="toggle-all" type="checkbox" v-model="allDone">
|
<input
|
||||||
|
id="toggle-all"
|
||||||
|
class="toggle-all"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="allDone"
|
||||||
|
/>
|
||||||
<label for="toggle-all">Mark all as complete</label>
|
<label for="toggle-all">Mark all as complete</label>
|
||||||
<ul class="todo-list">
|
<ul class="todo-list">
|
||||||
<li v-for="todo in filteredTodos"
|
<li
|
||||||
|
v-for="todo in filteredTodos"
|
||||||
class="todo"
|
class="todo"
|
||||||
:key="todo.id"
|
:key="todo.id"
|
||||||
:class="{ completed: todo.completed, editing: todo === editedTodo }">
|
:class="{ completed: todo.completed, editing: todo === editedTodo }"
|
||||||
|
>
|
||||||
<div class="view">
|
<div class="view">
|
||||||
<input class="toggle" type="checkbox" v-model="todo.completed">
|
<input class="toggle" type="checkbox" v-model="todo.completed" />
|
||||||
<label @dblclick="editTodo(todo)">{{ todo.title }}</label>
|
<label @dblclick="editTodo(todo)">{{ todo.title }}</label>
|
||||||
<button class="destroy" @click="removeTodo(todo)"></button>
|
<button class="destroy" @click="removeTodo(todo)"></button>
|
||||||
</div>
|
</div>
|
||||||
<input class="edit" type="text"
|
<input
|
||||||
|
class="edit"
|
||||||
|
type="text"
|
||||||
v-model="todo.title"
|
v-model="todo.title"
|
||||||
v-todo-focus="todo === editedTodo"
|
v-todo-focus="todo === editedTodo"
|
||||||
@blur="doneEdit(todo)"
|
@blur="doneEdit(todo)"
|
||||||
@keyup.enter="doneEdit(todo)"
|
@keyup.enter="doneEdit(todo)"
|
||||||
@keyup.escape="cancelEdit(todo)"
|
@keyup.escape="cancelEdit(todo)"
|
||||||
>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<footer class="footer" v-show="todos.length">
|
<footer class="footer" v-show="todos.length">
|
||||||
<span class="todo-count">
|
<span class="todo-count">
|
||||||
<strong>{{ remaining }}</strong> <span>{{ pluralize(remaining) }} left</span>
|
<strong>{{ remaining }}</strong>
|
||||||
|
<span>{{ pluralize(remaining) }} left</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="filters">
|
<ul class="filters">
|
||||||
<li><a href="#/all" :class="{ selected: visibility === 'all' }">All</a></li>
|
<li>
|
||||||
<li><a href="#/active" :class="{ selected: visibility === 'active' }">Active</a></li>
|
<a href="#/all" :class="{ selected: visibility === 'all' }">All</a>
|
||||||
<li><a href="#/completed" :class="{ selected: visibility === 'completed' }">Completed</a></li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#/active" :class="{ selected: visibility === 'active' }"
|
||||||
|
>Active</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#/completed"
|
||||||
|
:class="{ selected: visibility === 'completed' }"
|
||||||
|
>Completed</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button class="clear-completed" @click="removeCompleted" v-show="todos.length > remaining">
|
<button
|
||||||
|
class="clear-completed"
|
||||||
|
@click="removeCompleted"
|
||||||
|
v-show="todos.length > remaining"
|
||||||
|
>
|
||||||
Clear completed
|
Clear completed
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -63,7 +95,7 @@ const todoStorage = {
|
||||||
},
|
},
|
||||||
save(todos) {
|
save(todos) {
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = {
|
const filters = {
|
||||||
|
@ -71,7 +103,7 @@ const filters = {
|
||||||
return todos
|
return todos
|
||||||
},
|
},
|
||||||
active(todos) {
|
active(todos) {
|
||||||
return todos.filter((todo) => {
|
return todos.filter(todo => {
|
||||||
return !todo.completed
|
return !todo.completed
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -79,7 +111,7 @@ const filters = {
|
||||||
return todos.filter(function (todo) {
|
return todos.filter(function (todo) {
|
||||||
return todo.completed
|
return todo.completed
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
|
@ -88,7 +120,7 @@ Vue.createApp({
|
||||||
todos: todoStorage.fetch(),
|
todos: todoStorage.fetch(),
|
||||||
newTodo: '',
|
newTodo: '',
|
||||||
editedTodo: null,
|
editedTodo: null,
|
||||||
visibility: 'all'
|
visibility: 'all',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// watch todos change for localStorage persistence
|
// watch todos change for localStorage persistence
|
||||||
|
@ -97,8 +129,8 @@ Vue.createApp({
|
||||||
handler(todos) {
|
handler(todos) {
|
||||||
todoStorage.save(todos)
|
todoStorage.save(todos)
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -121,8 +153,8 @@ Vue.createApp({
|
||||||
this.todos.forEach(function (todo) {
|
this.todos.forEach(function (todo) {
|
||||||
todo.completed = value
|
todo.completed = value
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// methods that implement data logic.
|
// methods that implement data logic.
|
||||||
|
@ -136,7 +168,7 @@ Vue.createApp({
|
||||||
this.todos.push({
|
this.todos.push({
|
||||||
id: todoStorage.uid++,
|
id: todoStorage.uid++,
|
||||||
title: value,
|
title: value,
|
||||||
completed: false
|
completed: false,
|
||||||
})
|
})
|
||||||
this.newTodo = ''
|
this.newTodo = ''
|
||||||
},
|
},
|
||||||
|
@ -182,7 +214,7 @@ Vue.createApp({
|
||||||
|
|
||||||
pluralize(n) {
|
pluralize(n) {
|
||||||
return n === 1 ? 'item' : 'items'
|
return n === 1 ? 'item' : 'items'
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -190,7 +222,7 @@ Vue.createApp({
|
||||||
if (binding.value) {
|
if (binding.value) {
|
||||||
el.focus()
|
el.focus()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -26,18 +26,17 @@ const TreeItem = {
|
||||||
name: 'TreeItem', // necessary for self-reference
|
name: 'TreeItem', // necessary for self-reference
|
||||||
template: '#item-template',
|
template: '#item-template',
|
||||||
props: {
|
props: {
|
||||||
model: Object
|
model: Object,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
open: false
|
open: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isFolder() {
|
isFolder() {
|
||||||
return this.model.children &&
|
return this.model.children && this.model.children.length
|
||||||
this.model.children.length
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggle() {
|
toggle() {
|
||||||
|
@ -54,10 +53,10 @@ const TreeItem = {
|
||||||
},
|
},
|
||||||
addChild() {
|
addChild() {
|
||||||
this.model.children.push({
|
this.model.children.push({
|
||||||
name: 'new stuff'
|
name: 'new stuff',
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -79,32 +78,26 @@ const treeData = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'child folder',
|
name: 'child folder',
|
||||||
children: [
|
children: [{ name: 'hello' }, { name: 'wat' }],
|
||||||
{ name: 'hello' },
|
|
||||||
{ name: 'wat' }
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{ name: 'hello' },
|
{ name: 'hello' },
|
||||||
{ name: 'wat' },
|
{ name: 'wat' },
|
||||||
{
|
{
|
||||||
name: 'child folder',
|
name: 'child folder',
|
||||||
children: [
|
children: [{ name: 'hello' }, { name: 'wat' }],
|
||||||
{ name: 'hello' },
|
},
|
||||||
{ name: 'wat' }
|
],
|
||||||
]
|
},
|
||||||
}
|
],
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
TreeItem
|
TreeItem,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
treeData
|
treeData,
|
||||||
})
|
}),
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,28 @@
|
||||||
<div id="demo">
|
<div id="demo">
|
||||||
<h1>Latest Vue.js Commits</h1>
|
<h1>Latest Vue.js Commits</h1>
|
||||||
<template v-for="branch in branches">
|
<template v-for="branch in branches">
|
||||||
<input type="radio"
|
<input
|
||||||
|
type="radio"
|
||||||
:id="branch"
|
:id="branch"
|
||||||
:value="branch"
|
:value="branch"
|
||||||
name="branch"
|
name="branch"
|
||||||
v-model="currentBranch">
|
v-model="currentBranch"
|
||||||
|
/>
|
||||||
<label :for="branch">{{ branch }}</label>
|
<label :for="branch">{{ branch }}</label>
|
||||||
</template>
|
</template>
|
||||||
<p>vuejs/core@{{ currentBranch }}</p>
|
<p>vuejs/core@{{ currentBranch }}</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="{ html_url, sha, author, commit } in commits">
|
<li v-for="{ html_url, sha, author, commit } in commits">
|
||||||
<a :href="html_url" target="_blank" class="commit">{{ sha.slice(0, 7) }}</a>
|
<a :href="html_url" target="_blank" class="commit"
|
||||||
- <span class="message">{{ truncate(commit.message) }}</span><br>
|
>{{ sha.slice(0, 7) }}</a
|
||||||
by <span class="author"><a :href="author.html_url" target="_blank">{{ commit.author.name }}</a></span>
|
>
|
||||||
|
- <span class="message">{{ truncate(commit.message) }}</span><br />
|
||||||
|
by
|
||||||
|
<span class="author"
|
||||||
|
><a :href="author.html_url" target="_blank"
|
||||||
|
>{{ commit.author.name }}</a
|
||||||
|
></span
|
||||||
|
>
|
||||||
at <span class="date">{{ formatDate(commit.author.date) }}</span>
|
at <span class="date">{{ formatDate(commit.author.date) }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -51,9 +60,9 @@ createApp({
|
||||||
currentBranch,
|
currentBranch,
|
||||||
commits,
|
commits,
|
||||||
truncate,
|
truncate,
|
||||||
formatDate
|
formatDate,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -69,7 +78,8 @@ createApp({
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.author, .date {
|
.author,
|
||||||
|
.date {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -35,12 +35,12 @@ const DemoGrid = {
|
||||||
props: {
|
props: {
|
||||||
data: Array,
|
data: Array,
|
||||||
columns: Array,
|
columns: Array,
|
||||||
filterKey: String
|
filterKey: String,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
sortKey: '',
|
sortKey: '',
|
||||||
sortOrders: props.columns.reduce((o, key) => (o[key] = 1, o), {})
|
sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const filteredData = computed(() => {
|
const filteredData = computed(() => {
|
||||||
|
@ -74,28 +74,23 @@ const DemoGrid = {
|
||||||
state,
|
state,
|
||||||
filteredData,
|
filteredData,
|
||||||
sortBy,
|
sortBy,
|
||||||
capitalize
|
capitalize,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- App template (in DOM) -->
|
<!-- App template (in DOM) -->
|
||||||
<div id="demo">
|
<div id="demo">
|
||||||
<form id="search">
|
<form id="search">Search <input name="query" v-model="searchQuery" /></form>
|
||||||
Search <input name="query" v-model="searchQuery">
|
<demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery">
|
||||||
</form>
|
|
||||||
<demo-grid
|
|
||||||
:data="gridData"
|
|
||||||
:columns="gridColumns"
|
|
||||||
:filter-key="searchQuery">
|
|
||||||
</demo-grid>
|
</demo-grid>
|
||||||
</div>
|
</div>
|
||||||
<!-- App script -->
|
<!-- App script -->
|
||||||
<script>
|
<script>
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
DemoGrid
|
DemoGrid,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
|
@ -104,15 +99,18 @@ Vue.createApp({
|
||||||
{ name: 'Chuck Norris', power: Infinity },
|
{ name: 'Chuck Norris', power: Infinity },
|
||||||
{ name: 'Bruce Lee', power: 9000 },
|
{ name: 'Bruce Lee', power: 9000 },
|
||||||
{ name: 'Jackie Chan', power: 7000 },
|
{ name: 'Jackie Chan', power: 7000 },
|
||||||
{ name: 'Jet Li', power: 8000 }
|
{ name: 'Jet Li', power: 8000 },
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +135,8 @@ td {
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,27 +13,34 @@ const { ref, computed } = Vue
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
setup() {
|
setup() {
|
||||||
const input = ref('# hello')
|
const input = ref('# hello')
|
||||||
const output = computed(() => marked.marked(input.value, { sanitize: true }))
|
const output = computed(() =>
|
||||||
const update = _.debounce(e => { input.value = e.target.value }, 50)
|
marked.marked(input.value, { sanitize: true }),
|
||||||
|
)
|
||||||
|
const update = _.debounce(e => {
|
||||||
|
input.value = e.target.value
|
||||||
|
}, 50)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
input,
|
input,
|
||||||
output,
|
output,
|
||||||
update
|
update,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}).mount('#editor')
|
}).mount('#editor')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
html, body, #editor {
|
html,
|
||||||
|
body,
|
||||||
|
#editor {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea, #editor div {
|
textarea,
|
||||||
|
#editor div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
|
@ -6,14 +6,14 @@ const { ref, reactive, computed, createApp } = Vue
|
||||||
function valueToPoint(value, index, total) {
|
function valueToPoint(value, index, total) {
|
||||||
var x = 0
|
var x = 0
|
||||||
var y = -value * 0.8
|
var y = -value * 0.8
|
||||||
var angle = Math.PI * 2 / total * index
|
var angle = ((Math.PI * 2) / total) * index
|
||||||
var cos = Math.cos(angle)
|
var cos = Math.cos(angle)
|
||||||
var sin = Math.sin(angle)
|
var sin = Math.sin(angle)
|
||||||
var tx = x * cos - y * sin + 100
|
var tx = x * cos - y * sin + 100
|
||||||
var ty = x * sin + y * cos + 100
|
var ty = x * sin + y * cos + 100
|
||||||
return {
|
return {
|
||||||
x: tx,
|
x: tx,
|
||||||
y: ty
|
y: ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,17 +22,15 @@ const AxisLabel = {
|
||||||
props: {
|
props: {
|
||||||
stat: Object,
|
stat: Object,
|
||||||
index: Number,
|
index: Number,
|
||||||
total: Number
|
total: Number,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
return {
|
return {
|
||||||
point: computed(() => valueToPoint(
|
point: computed(() =>
|
||||||
+props.stat.value + 10,
|
valueToPoint(+props.stat.value + 10, props.index, props.total),
|
||||||
props.index,
|
),
|
||||||
props.total
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -58,16 +56,18 @@ const Polygraph = {
|
||||||
return {
|
return {
|
||||||
points: computed(() => {
|
points: computed(() => {
|
||||||
const total = props.stats.length
|
const total = props.stats.length
|
||||||
return props.stats.map((stat, i) => {
|
return props.stats
|
||||||
|
.map((stat, i) => {
|
||||||
const point = valueToPoint(stat.value, i, total)
|
const point = valueToPoint(stat.value, i, total)
|
||||||
return point.x + ',' + point.y
|
return point.x + ',' + point.y
|
||||||
}).join(' ')
|
|
||||||
})
|
})
|
||||||
|
.join(' ')
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
AxisLabel
|
AxisLabel,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -80,12 +80,12 @@ const Polygraph = {
|
||||||
<!-- controls -->
|
<!-- controls -->
|
||||||
<div v-for="stat in stats">
|
<div v-for="stat in stats">
|
||||||
<label>{{stat.label}}</label>
|
<label>{{stat.label}}</label>
|
||||||
<input type="range" v-model="stat.value" min="0" max="100">
|
<input type="range" v-model="stat.value" min="0" max="100" />
|
||||||
<span>{{stat.value}}</span>
|
<span>{{stat.value}}</span>
|
||||||
<button @click="remove(stat)" class="remove">X</button>
|
<button @click="remove(stat)" class="remove">X</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="add">
|
<form id="add">
|
||||||
<input name="newlabel" v-model="newLabel">
|
<input name="newlabel" v-model="newLabel" />
|
||||||
<button @click="add">Add a Stat</button>
|
<button @click="add">Add a Stat</button>
|
||||||
</form>
|
</form>
|
||||||
<pre id="raw">{{ stats }}</pre>
|
<pre id="raw">{{ stats }}</pre>
|
||||||
|
@ -98,12 +98,12 @@ const globalStats = [
|
||||||
{ label: 'C', value: 100 },
|
{ label: 'C', value: 100 },
|
||||||
{ label: 'D', value: 100 },
|
{ label: 'D', value: 100 },
|
||||||
{ label: 'E', value: 100 },
|
{ label: 'E', value: 100 },
|
||||||
{ label: 'F', value: 100 }
|
{ label: 'F', value: 100 },
|
||||||
]
|
]
|
||||||
|
|
||||||
createApp({
|
createApp({
|
||||||
components: {
|
components: {
|
||||||
Polygraph
|
Polygraph,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const newLabel = ref('')
|
const newLabel = ref('')
|
||||||
|
@ -114,7 +114,7 @@ createApp({
|
||||||
if (!newLabel.value) return
|
if (!newLabel.value) return
|
||||||
stats.push({
|
stats.push({
|
||||||
label: newLabel.value,
|
label: newLabel.value,
|
||||||
value: 100
|
value: 100,
|
||||||
})
|
})
|
||||||
newLabel.value = ''
|
newLabel.value = ''
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ createApp({
|
||||||
if (stats.length > 3) {
|
if (stats.length > 3) {
|
||||||
stats.splice(stats.indexOf(stat), 1)
|
stats.splice(stats.indexOf(stat), 1)
|
||||||
} else {
|
} else {
|
||||||
alert('Can\'t delete more!')
|
alert("Can't delete more!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,20 +131,23 @@ createApp({
|
||||||
newLabel,
|
newLabel,
|
||||||
stats,
|
stats,
|
||||||
add,
|
add,
|
||||||
remove
|
remove,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
polygon {
|
polygon {
|
||||||
fill: #42b983;
|
fill: #42b983;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle {
|
circle {
|
||||||
|
@ -153,7 +156,10 @@ circle {
|
||||||
}
|
}
|
||||||
|
|
||||||
text {
|
text {
|
||||||
font-family: Helvetica Neue, Arial, sans-serif;
|
font-family:
|
||||||
|
Helvetica Neue,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
fill: #666;
|
fill: #666;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,51 @@
|
||||||
<script src="../../dist/vue.global.js"></script>
|
<script src="../../dist/vue.global.js"></script>
|
||||||
<link rel="stylesheet" href="../../../../node_modules/todomvc-app-css/index.css">
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="../../../../node_modules/todomvc-app-css/index.css"
|
||||||
|
/>
|
||||||
|
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<section class="todoapp">
|
<section class="todoapp">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<h1>todos</h1>
|
<h1>todos</h1>
|
||||||
<input class="new-todo"
|
<input
|
||||||
autofocus autocomplete="off"
|
class="new-todo"
|
||||||
|
autofocus
|
||||||
|
autocomplete="off"
|
||||||
placeholder="What needs to be done?"
|
placeholder="What needs to be done?"
|
||||||
v-model="state.newTodo"
|
v-model="state.newTodo"
|
||||||
@keyup.enter="addTodo">
|
@keyup.enter="addTodo"
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
<section class="main" v-show="state.todos.length">
|
<section class="main" v-show="state.todos.length">
|
||||||
<input id="toggle-all" class="toggle-all" type="checkbox" v-model="state.allDone">
|
<input
|
||||||
|
id="toggle-all"
|
||||||
|
class="toggle-all"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="state.allDone"
|
||||||
|
/>
|
||||||
<label for="toggle-all">Mark all as complete</label>
|
<label for="toggle-all">Mark all as complete</label>
|
||||||
<ul class="todo-list">
|
<ul class="todo-list">
|
||||||
<li v-for="todo in state.filteredTodos"
|
<li
|
||||||
|
v-for="todo in state.filteredTodos"
|
||||||
class="todo"
|
class="todo"
|
||||||
:key="todo.id"
|
:key="todo.id"
|
||||||
:class="{ completed: todo.completed, editing: todo === state.editedTodo }">
|
:class="{ completed: todo.completed, editing: todo === state.editedTodo }"
|
||||||
|
>
|
||||||
<div class="view">
|
<div class="view">
|
||||||
<input class="toggle" type="checkbox" v-model="todo.completed">
|
<input class="toggle" type="checkbox" v-model="todo.completed" />
|
||||||
<label @dblclick="editTodo(todo)">{{ todo.title }}</label>
|
<label @dblclick="editTodo(todo)">{{ todo.title }}</label>
|
||||||
<button class="destroy" @click="removeTodo(todo)"></button>
|
<button class="destroy" @click="removeTodo(todo)"></button>
|
||||||
</div>
|
</div>
|
||||||
<input class="edit" type="text"
|
<input
|
||||||
|
class="edit"
|
||||||
|
type="text"
|
||||||
v-model="todo.title"
|
v-model="todo.title"
|
||||||
v-todo-focus="todo === state.editedTodo"
|
v-todo-focus="todo === state.editedTodo"
|
||||||
@blur="doneEdit(todo)"
|
@blur="doneEdit(todo)"
|
||||||
@keyup.enter="doneEdit(todo)"
|
@keyup.enter="doneEdit(todo)"
|
||||||
@keyup.escape="cancelEdit(todo)"
|
@keyup.escape="cancelEdit(todo)"
|
||||||
>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
@ -40,12 +55,32 @@
|
||||||
<span>{{ state.remainingText }}</span>
|
<span>{{ state.remainingText }}</span>
|
||||||
</span>
|
</span>
|
||||||
<ul class="filters">
|
<ul class="filters">
|
||||||
<li><a href="#/all" :class="{ selected: state.visibility === 'all' }">All</a></li>
|
<li>
|
||||||
<li><a href="#/active" :class="{ selected: state.visibility === 'active' }">Active</a></li>
|
<a href="#/all" :class="{ selected: state.visibility === 'all' }"
|
||||||
<li><a href="#/completed" :class="{ selected: state.visibility === 'completed' }">Completed</a></li>
|
>All</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#/active"
|
||||||
|
:class="{ selected: state.visibility === 'active' }"
|
||||||
|
>Active</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#/completed"
|
||||||
|
:class="{ selected: state.visibility === 'completed' }"
|
||||||
|
>Completed</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<button class="clear-completed" @click="removeCompleted" v-show="state.todos.length > state.remaining">
|
<button
|
||||||
|
class="clear-completed"
|
||||||
|
@click="removeCompleted"
|
||||||
|
v-show="state.todos.length > state.remaining"
|
||||||
|
>
|
||||||
Clear completed
|
Clear completed
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -53,7 +88,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const { createApp, reactive, computed, watchEffect, onMounted, onUnmounted } = Vue
|
const { createApp, reactive, computed, watchEffect, onMounted, onUnmounted } =
|
||||||
|
Vue
|
||||||
|
|
||||||
const STORAGE_KEY = 'todos-vuejs-3.x'
|
const STORAGE_KEY = 'todos-vuejs-3.x'
|
||||||
const todoStorage = {
|
const todoStorage = {
|
||||||
|
@ -67,7 +103,7 @@ const todoStorage = {
|
||||||
},
|
},
|
||||||
save(todos) {
|
save(todos) {
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = {
|
const filters = {
|
||||||
|
@ -75,7 +111,7 @@ const filters = {
|
||||||
return todos
|
return todos
|
||||||
},
|
},
|
||||||
active(todos) {
|
active(todos) {
|
||||||
return todos.filter((todo) => {
|
return todos.filter(todo => {
|
||||||
return !todo.completed
|
return !todo.completed
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -83,7 +119,7 @@ const filters = {
|
||||||
return todos.filter(function (todo) {
|
return todos.filter(function (todo) {
|
||||||
return todo.completed
|
return todo.completed
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function pluralize(n) {
|
function pluralize(n) {
|
||||||
|
@ -112,11 +148,11 @@ createApp({
|
||||||
return state.remaining === 0
|
return state.remaining === 0
|
||||||
},
|
},
|
||||||
set: function (value) {
|
set: function (value) {
|
||||||
state.todos.forEach((todo) => {
|
state.todos.forEach(todo => {
|
||||||
todo.completed = value
|
todo.completed = value
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
@ -150,7 +186,7 @@ createApp({
|
||||||
state.todos.push({
|
state.todos.push({
|
||||||
id: todoStorage.uid++,
|
id: todoStorage.uid++,
|
||||||
title: value,
|
title: value,
|
||||||
completed: false
|
completed: false,
|
||||||
})
|
})
|
||||||
state.newTodo = ''
|
state.newTodo = ''
|
||||||
}
|
}
|
||||||
|
@ -191,7 +227,7 @@ createApp({
|
||||||
editTodo,
|
editTodo,
|
||||||
doneEdit,
|
doneEdit,
|
||||||
cancelEdit,
|
cancelEdit,
|
||||||
removeCompleted
|
removeCompleted,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -200,7 +236,7 @@ createApp({
|
||||||
if (value) {
|
if (value) {
|
||||||
el.focus()
|
el.focus()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -28,14 +28,14 @@ const TreeItem = {
|
||||||
name: 'TreeItem', // necessary for self-reference
|
name: 'TreeItem', // necessary for self-reference
|
||||||
template: '#item-template',
|
template: '#item-template',
|
||||||
props: {
|
props: {
|
||||||
model: Object
|
model: Object,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
open: false,
|
open: false,
|
||||||
isFolder: computed(() => {
|
isFolder: computed(() => {
|
||||||
return props.model.children && props.model.children.length
|
return props.model.children && props.model.children.length
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
|
@ -58,9 +58,9 @@ const TreeItem = {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
toggle,
|
toggle,
|
||||||
changeType,
|
changeType,
|
||||||
addChild
|
addChild,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -82,32 +82,26 @@ const treeData = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'child folder',
|
name: 'child folder',
|
||||||
children: [
|
children: [{ name: 'hello' }, { name: 'wat' }],
|
||||||
{ name: 'hello' },
|
|
||||||
{ name: 'wat' }
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{ name: 'hello' },
|
{ name: 'hello' },
|
||||||
{ name: 'wat' },
|
{ name: 'wat' },
|
||||||
{
|
{
|
||||||
name: 'child folder',
|
name: 'child folder',
|
||||||
children: [
|
children: [{ name: 'hello' }, { name: 'wat' }],
|
||||||
{ name: 'hello' },
|
},
|
||||||
{ name: 'wat' }
|
],
|
||||||
]
|
},
|
||||||
}
|
],
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
TreeItem
|
TreeItem,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
treeData
|
treeData,
|
||||||
})
|
}),
|
||||||
}).mount('#demo')
|
}).mount('#demo')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
<button @click="reset">reset</button>
|
<button @click="reset">reset</button>
|
||||||
<button @click="shuffle">shuffle</button>
|
<button @click="shuffle">shuffle</button>
|
||||||
<transition-group tag="ul" name="fade" class="container">
|
<transition-group tag="ul" name="fade" class="container">
|
||||||
<item v-for="item in items"
|
<item
|
||||||
|
v-for="item in items"
|
||||||
class="item"
|
class="item"
|
||||||
:msg="item"
|
:msg="item"
|
||||||
:key="item"
|
:key="item"
|
||||||
@rm="remove(item)">
|
@rm="remove(item)"
|
||||||
|
>
|
||||||
</item>
|
</item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,16 +23,16 @@ let id = getInitialItems().length + 1
|
||||||
|
|
||||||
const Item = {
|
const Item = {
|
||||||
props: ['msg'],
|
props: ['msg'],
|
||||||
template: `<div>{{ msg }} <button @click="$emit('rm')">x</button></div>`
|
template: `<div>{{ msg }} <button @click="$emit('rm')">x</button></div>`,
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: {
|
components: {
|
||||||
Item
|
Item,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
items: getInitialItems()
|
items: getInitialItems(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -49,8 +51,8 @@ Vue.createApp({
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
this.items.splice(i, 1)
|
this.items.splice(i, 1)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -67,11 +69,14 @@ Vue.createApp({
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
/* 1. declare transition */
|
/* 1. declare transition */
|
||||||
.fade-move, .fade-enter-active, .fade-leave-active {
|
.fade-move,
|
||||||
transition: all .5s cubic-bezier(.55,0,.1,1);
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
|
||||||
}
|
}
|
||||||
/* 2. declare enter from and leave to state */
|
/* 2. declare enter from and leave to state */
|
||||||
.fade-enter-from, .fade-leave-to {
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleY(0.01) translate(30px, 0);
|
transform: scaleY(0.01) translate(30px, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<script>
|
<script>
|
||||||
const Modal = {
|
const Modal = {
|
||||||
template: '#modal-template',
|
template: '#modal-template',
|
||||||
props: ['show']
|
props: ['show'],
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ const Modal = {
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
components: { Modal },
|
components: { Modal },
|
||||||
data: () => ({
|
data: () => ({
|
||||||
showModal: false
|
showModal: false,
|
||||||
})
|
}),
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ Vue.createApp({
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, .5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
display: table;
|
display: table;
|
||||||
transition: opacity .3s ease;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-wrapper {
|
.modal-wrapper {
|
||||||
|
@ -88,8 +88,8 @@ Vue.createApp({
|
||||||
padding: 20px 30px;
|
padding: 20px 30px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
|
||||||
transition: all .3s ease;
|
transition: all 0.3s ease;
|
||||||
font-family: Helvetica, Arial, sans-serif;
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue