Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d83c722

Browse files
Merge pull request vuejs#275 from vuejs/master
获取官方更新 11.15
2 parents 3b0566f + bcd5049 commit d83c722

File tree

8 files changed

+283
-21
lines changed

8 files changed

+283
-21
lines changed

‎src/v2/api/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,7 @@ All lifecycle hooks automatically have their `this` context bound to the instanc
16211621
`ref` is used to register a reference to an element or a child component. The reference will be registered under the parent component's `$refs` object. If used on a plain DOM element, the reference will be that element; if used on a child component, the reference will be component instance:
16221622

16231623
``` html
1624-
<!-- vm.$refs.p will the DOM node -->
1624+
<!-- vm.$refs.p will be the DOM node -->
16251625
<p ref="p">hello</p>
16261626

16271627
<!-- vm.$refs.child will be the child comp instance -->
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
---
2+
title: Adding Instance Properties
3+
type: cookbook
4+
order: 1.1
5+
---
6+
7+
## Simple Example
8+
9+
There may be data/utilities you'd like to use in many components, but you don't want to [pollute the global scope](https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch3.md). In these cases, you can make them available to each Vue instance by defining them on the prototype:
10+
11+
``` js
12+
Vue.prototype.$appName = 'My App'
13+
```
14+
15+
Now `$appName` is available on all Vue instances, even before creation. If we run:
16+
17+
``` js
18+
new Vue({
19+
beforeCreate: function () {
20+
console.log(this.$appName)
21+
}
22+
})
23+
```
24+
25+
Then `"My App"` will be logged to the console. It's that simple!
26+
27+
## The Importance of Scoping Instance Properties
28+
29+
You may be wondering:
30+
31+
> "Why does `appName` start with `$`? Is that important? What does it do?
32+
33+
No magic is happening here. `$` is simply a convention Vue uses for properties that are available to all instances. This avoids conflicts with any defined data, computed properties, or methods.
34+
35+
> "Conflicts? What do you mean?"
36+
37+
Another great question! If you just set:
38+
39+
``` js
40+
Vue.prototype.appName = 'My App'
41+
```
42+
43+
Then what would you expect to be logged below?
44+
45+
``` js
46+
new Vue({
47+
data: {
48+
// Uh oh - appName is *also* the name of the
49+
// instance property we just defined!
50+
appName: 'The name of some other app'
51+
},
52+
beforeCreate: function () {
53+
console.log(this.appName)
54+
},
55+
created: function () {
56+
console.log(this.appName)
57+
}
58+
})
59+
```
60+
61+
It would be `"The name of some other app"`, then `"My App"`, because `this.appName` is overwritten ([sort of](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md)) by `data` when the instance is created. We scope instance properties with `$` to avoid this. You can even use your own convention if you'd like, such as `$_appName` or `ΩappName`, to prevent even conflicts with plugins or future features.
62+
63+
## Real-World Example: Replacing Vue Resource with Axios
64+
65+
Let's say you're replacing the [now-retired Vue Resource](https://medium.com/the-vue-point/retiring-vue-resource-871a82880af4). You really enjoyed accessing request methods through `this.$http` and you want to do the same thing with Axios instead.
66+
67+
All you have to do is include axios in your project:
68+
69+
``` html
70+
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.2/axios.js"></script>
71+
72+
<div id="app">
73+
<ul>
74+
<li v-for="user in users">{{ user.name }}</li>
75+
</ul>
76+
</div>
77+
```
78+
79+
Alias `axios` to `Vue.prototype.$http`:
80+
81+
``` js
82+
Vue.prototype.$http = axios
83+
```
84+
85+
Then you'll be able to use methods like `this.$http.get` in any Vue instance:
86+
87+
``` js
88+
new Vue({
89+
el: '#app',
90+
data: {
91+
users: []
92+
},
93+
created () {
94+
var vm = this
95+
this.$http.get('https://jsonplaceholder.typicode.com/users')
96+
.then(function (response) {
97+
vm.users = response.data
98+
})
99+
}
100+
})
101+
```
102+
103+
## The Context of Prototype Methods
104+
105+
In case you're not aware, methods added to a prototype in JavaScript gain the context of the instance. That means they can use `this` to access data, computed properties, methods, or anything else defined on the instance.
106+
107+
Let's take advantage of this in a `$reverseText` method:
108+
109+
``` js
110+
Vue.prototype.$reverseText = function (propertyName) {
111+
this[propertyName] = this[propertyName].split('').reverse().join('')
112+
}
113+
114+
new Vue({
115+
data: {
116+
message: 'Hello '
117+
},
118+
created: function () {
119+
console.log(this.message) // => "Hello"
120+
this.$reverseText('message')
121+
console.log(this.message) // => "olleH"
122+
}
123+
})
124+
```
125+
126+
Note that the context binding will __not__ work if you use an ES6/2015 arrow function, as they implicitly bind to their parent scope. That means the arrow function version:
127+
128+
``` js
129+
Vue.prototype.$reverseText = propertyName => {
130+
this[propertyName] = this[propertyName].split('').reverse().join('')
131+
}
132+
```
133+
134+
Would throw an error:
135+
136+
``` log
137+
Uncaught TypeError: Cannot read property 'split' of undefined
138+
```
139+
140+
## When To Avoid This Pattern
141+
142+
As long as you're vigilant in scoping prototype properties, using this pattern is quite safe - as in, unlikely to produce bugs.
143+
144+
However, it can sometimes cause confusion with other developers. They might see `this.$http`, for example, and think, "Oh, I didn't know about this Vue feature!" Then they move to a different project and are confused when `this.$http` is undefined. Or, maybe they want to Google how to do something, but can't find results because they don't realize they're actually using Axios under an alias.
145+
146+
__The convenience comes at the cost of explicitness.__ When just looking at a component, it's impossible to tell where `$http` came from. Vue itself? A plugin? A coworker?
147+
148+
So what are the alternatives?
149+
150+
## Alternative Patterns
151+
152+
### When Not Using a Module System
153+
154+
In applications with __no__ module system (e.g. via Webpack or Browserify), there's a pattern that's often used with _any_ JavaScript-enhanced frontend: a global `App` object.
155+
156+
If what you want to add has nothing to do with Vue specifically, this may be a good alternative to reach for. Here's an example:
157+
158+
``` js
159+
var App = Object.freeze({
160+
name: 'My App',
161+
description: '2.1.4',
162+
helpers: {
163+
// This is a purely functional version of
164+
// the $reverseText method we saw earlier
165+
reverseText: function (text) {
166+
return text.split('').reverse().join('')
167+
}
168+
}
169+
})
170+
```
171+
172+
<p class="tip">If you raised an eyebrow at `Object.freeze`, what it does is prevent the object from being changed in the future. This essentially makes all its properties constants, protecting you from future state bugs.</p>
173+
174+
Now the source of these shared properties is much more obvious: there's an `App` object defined somewhere in the app. To find it, developers need only run a project-wide search.
175+
176+
Another advantage is that `App` can now be used _anywhere_ in your code, whether it's Vue-related or not. That includes attaching values directly to instance options, rather than having to enter a function to access properties on `this`:
177+
178+
``` js
179+
new Vue({
180+
data: {
181+
appVersion: App.version
182+
},
183+
methods: {
184+
reverseText: App.helpers.reverseText
185+
}
186+
})
187+
```
188+
189+
### When Using a Module System
190+
191+
When you have access to a module system, you can easily organize shared code into modules, then `require`/`import` those modules wherever they're needed. This is the epitome of explicitness, because in each file you gain a list of dependencies. You know _exactly_ each one came from.
192+
193+
While certainly more verbose, this approach is definitely the most maintainable, especially when working with other developers and/or building a large app.

‎src/v2/cookbook/index.md‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Introduction
3+
type: cookbook
4+
order: 0
5+
---
6+
7+
## WORK IN PROGRESS
8+
9+
<p class="tip">This cookbook is still in its very early stages. At this point, we will not be linking to it from anywhere else. Pages may be removed or reorganized at any time. Even the goals and overall format are still in flux.</p>
10+
11+
## The Cookbook vs the Guide
12+
13+
How is the cookbook different from the guide? Why is this necessary?
14+
15+
- __Greater Focus__: In the guide, we're essentially telling a story. Each section builds on and assumes knowledge from each previous section. In the cookbook, each recipe can and should stand on its own. This means recipes can focus on one specific aspect of Vue, rather than having to give a general overview.
16+
17+
- __Greater Depth__: To avoid making the guide too long, we try to include only the simplest possible examples to help you understand each feature. Then we move on. In the cookbook, we can include more complex examples, combining features in interesting ways. Each recipe can also be as long and detailed as it needs to be, in order to fully explore its niche.
18+
19+
- __Teaching JavaScript__: In the guide, we assume at least intermediate familiarity with ES5 JavaScript. For example, we won't explain how `Array.prototype.filter` works in a computed property that filters a list. In the cookbook however, essential JavaScript features (including ES6/2015+) can be explored and explained in the context of how they help us build better Vue applications.
20+
21+
- __Exploring the Ecosystem__: For advanced features, we assume some ecosystem knowledge. For example, if you want to use single-file components in Webpack, we don't explain how to configure the non-Vue parts of the Webpack config. In the cookbook, we have the space to explore these ecosystem libraries in more depth - at least to the extent that is universally useful for Vue developers.
22+
23+
## Guidelines for Recipes
24+
25+
Recipes should generally:
26+
27+
> 1. Solve a specific, common problem
28+
29+
> 2. Start with the simplest possible example
30+
31+
> 3. Introduce complexities one at a time
32+
33+
> 4. Link to other docs, rather than re-explaining concepts
34+
35+
> 5. Describe the problem, rather than assuming familiarity
36+
37+
> 6. Explain the process, rather than just the end result
38+
39+
> 7. Explain the pros and cons of your strategy, including when it is and isn't appropriate
40+
41+
> 8. Mention alternative solutions, if relevant, but leave in-depth explorations to a separate recipe
42+

‎src/v2/guide/comparison.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ Vue on the other hand, gives you full access to CSS within [single-file componen
186186

187187
The optional `scoped` attribute automatically scopes this CSS to your component by adding a unique attribute (such as `data-v-21e5b78`) to elements and compiling `.list-container:hover` to something like `.list-container[data-v-21e5b78]:hover`.
188188

189+
If you are already familiar with CSS Modules, Vue single file components also have [first-class support for it](http://vue-loader.vuejs.org/en/features/css-modules.html).
190+
189191
Finally, just as with HTML, you also have the option of writing your CSS using any preprocessors (or post-processors) you'd like, allowing you to leverage existing libraries in those ecosystems. You can also perform design-centric operations such as color manipulation during your build process, rather than importing specialized JavaScript libraries that would increase the size of your build and complexity of your application.
190192

191193
### Scale

‎src/v2/guide/index.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,10 @@ Vue.component('todo-item', {
270270
Now you can compose it in another component's template:
271271

272272
``` html
273-
<ul>
273+
<ol>
274274
<!-- Create an instance of the todo-item component -->
275275
<todo-item></todo-item>
276-
</ul>
276+
</ol>
277277
```
278278

279279
But this would render the same text for every todo, which is not super interesting. We should be able to pass data from the parent scope into child components. Let's modify the component definition to make it accept a [prop](components.html#Props):

‎themes/vue/layout/layout.ejs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,15 @@
7272
'#search-query-sidebar'
7373
].forEach(function (selector) {
7474
if (!document.querySelector(selector)) return
75+
// search index defaults to v2
76+
var match = window.location.pathname.match(/^\/(v\d+)/)
77+
var version = match ? match[1] : 'v2'
7578
docsearch({
7679
appId: 'BH4D9OD16A',
7780
apiKey: '85cc3221c9f23bfbaa4e3913dd7625ea',
7881
indexName: 'vuejs',
79-
inputSelector: selector
82+
inputSelector: selector,
83+
algoliaOptions: { facetFilters: ["version:" + version] }
8084
})
8185
})
8286
</script>

‎themes/vue/layout/partials/sidebar.ejs‎

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,52 @@
99
</div>
1010
<h2>
1111
<%- type === 'api' ? 'API' : (type.charAt(0).toUpperCase() + type.slice(1)) %>
12-
<select class="version-select">
13-
<option value="SELF" selected>2.0</option>
14-
<option value="v1">1.0</option>
15-
<option value="012">0.12</option>
16-
<option value="011">0.11</option>
17-
</select>
12+
<% if (type !== 'cookbook') { %>
13+
<select class="version-select">
14+
<option value="SELF" selected>2.0</option>
15+
<option value="v1">1.0</option>
16+
<option value="012">0.12</option>
17+
<option value="011">0.11</option>
18+
</select>
19+
<% } %>
1820
</h2>
1921
<ul class="menu-root">
2022
<% type !== 'api' && site.pages.find({type: type}).sort('order').each(function (p) { %>
2123
<% var fileName = p.path.replace(/^.+?\/([\w-]+)\.html/, '1ドル') %>
22-
<% if (fileName === 'installation') { %>
23-
<li><h3>Essentials</h3></li>
24+
<% if (type === 'guide') { %>
25+
<% if (fileName === 'installation') { %>
26+
<li><h3>Essentials</h3></li>
27+
<% } %>
28+
<% if (fileName === 'reactivity') { %>
29+
<li><h3>Advanced</h3></li>
30+
<% } %>
31+
<% if (fileName === 'migration') { %>
32+
<li><h3>Migrating</h3></li>
33+
<% } %>
34+
<% if (fileName === 'comparison') { %>
35+
<li><h3>Meta</h3></li>
36+
<% } %>
2437
<% } %>
25-
<% if (fileName === 'reactivity') { %>
26-
<li><h3>Advanced</h3></li>
27-
<% } %>
28-
<% if (fileName === 'migration') { %>
29-
<li><h3>Migrating</h3></li>
30-
<% } %>
31-
<% if (fileName === 'comparison') { %>
32-
<li><h3>Meta</h3></li>
38+
<% if (type === 'cookbook') { %>
39+
<% if (p.order === 1.1) { %>
40+
<li><h3>Vue Instance</h3></li>
41+
<% } %>
42+
<!-- Move cookbook sections here once they have -->
43+
<!-- at least one recipe -->
3344
<% } %>
3445
<li>
3546
<a href="/<%- p.path %>" class="sidebar-link<%- page.title === p.title ? ' current' : '' %><%- p.is_new ? ' new' : '' %>"><%- p.title %></a>
3647
</li>
3748
<% }) %>
49+
<% if (type === 'cookbook') { %>
50+
<li><h3>Components</h3></li>
51+
<li><h4>Form Inputs</h4></li>
52+
<li><h4>3rd-Party Integrations</h4></li>
53+
<li><h3>Transitions</h3></li>
54+
<li><h3>Directives</h3></li>
55+
<li><h3>Vue Router</h3></li>
56+
<li><h3>Vuex</h3></li>
57+
<% } %>
3858
</ul>
3959
</div>
4060
</div>

‎themes/vue/source/js/common.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@
9999

100100
function initVersionSelect () {
101101
// version select
102-
document.querySelector('.version-select').addEventListener('change', function (e) {
102+
var versionSelect = document.querySelector('.version-select')
103+
versionSelect && versionSelect.addEventListener('change', function (e) {
103104
var version = e.target.value
104105
var section = window.location.pathname.match(/\/v\d\/(\w+?)\//)[1]
105106
if (version === 'SELF') return

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /