Skip to content

Commit da55ffc

Browse files
committed
first commiy
0 parents  commit da55ffc

File tree

10 files changed

+499
-0
lines changed

10 files changed

+499
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vscode

Diff for: components/README.md

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Components
2+
3+
We declare a component by using the `Vue` object and calling its component method with two arguments:
4+
5+
* component name
6+
* component definition object
7+
8+
```
9+
Vue.component('person-detail', {
10+
template: `<div>a component</div>`
11+
})
12+
```
13+
14+
Declaring the above means we can start adding this component wherever we need it, like so:
15+
16+
```
17+
<person-detail>
18+
```
19+
20+
## Adding input property
21+
22+
We are going to want to add an input property to the component so we can pass data for it to render. We do that by doing the following:
23+
24+
* adding v-bind directive when creating the component
25+
* adding a `props` property to component definition
26+
27+
```
28+
Vue.component('person-detail', {
29+
template: `<div>{{person.name}}</div>`,
30+
props: ['person']
31+
})
32+
```
33+
34+
We did two things above, we added the `props` to our component definition object. We also updated the template to render our property like so:
35+
36+
```
37+
template: `<div>{{person.name}}</div>`
38+
```
39+
40+
At this point we need to creating the binding in the markup. We create this binding by using the structural directive `v-bind`, like so:
41+
42+
```
43+
<div v-bind:nameOfProperty="property">
44+
```
45+
46+
For our component it means we change it to the following:
47+
48+
```
49+
<person-detail v-bind:person="person">
50+
```
51+
52+
This of course means that the context this component lives in knows about `person`, like so:
53+
54+
```
55+
var app = new Vue({
56+
el: '#app',
57+
data: {
58+
person: {
59+
name: 'chris'
60+
}
61+
}
62+
})
63+
```
64+
65+
### Naming
66+
67+
So far we have been using the `v-bind:propertyInComponent` binding syntax, but it is a bit verbose. We can shorten this to `:propertyInComponent`. There is another naming convention that we need to know about. When we name things in our props of our component like so:
68+
69+
```
70+
Vue.component('component', {
71+
props : ['title','longTitle']
72+
});
73+
```
74+
75+
The casing we use matter. When we create our component in markup, we need to name it correctly
76+
77+
* title becomes title
78+
BUT
79+
* longTitle becomes long-title when used in the markup
80+
81+
```
82+
<component long-title="someProp">
83+
```
84+
85+
### More on binding
86+
87+
We can bind anything to a component, a primitive like a string, number or boolean or a list and even an object. However there is a difference in how different types behave. Primitives are being one-time binded so binding against the following primitives, would be one-time:
88+
89+
```
90+
<component :show="show" :title="title" :counter="counter" >
91+
```
92+
93+
Binding to an object would be another thing though:
94+
95+
```
96+
<component :person="person" >
97+
```
98+
99+
The above shows how we bind towards the property `person` and binds it to an object that may look like this:
100+
101+
```
102+
{
103+
name: 'chris'
104+
}
105+
```
106+
107+
Changing the property inside of the component with a `v-model`, like so:
108+
109+
```
110+
<input v-model="person.name">
111+
```
112+
113+
would lead to even the parent object being affected.
114+
115+
### fixing the double binding
116+
117+
What you usually want when you bind in a list or object is to change things in the component first and when you are happy with it you invoke an action so the parent knows all about this updated list or object. You usually don't want the parent to be alerted about every change that you do. You can fix this by using the `data()` method with the component like so:
118+
119+
```
120+
data() {
121+
const copyObject = Object.assign({}, this.object);
122+
123+
const copyList = this.list.map(item => Object.assign(item));
124+
125+
return {
126+
copyObject,
127+
copyList
128+
};
129+
130+
}
131+
```
132+
133+
## Output
134+
135+
How do we communicate with upwards, i.e how do we invoke a method, simple, we can just bind a method to it like so:
136+
137+
```
138+
<component v-on:customEventName="method" v-bind:prop="prop">
139+
```
140+
141+
The above tells us that we can call the event whatever we want, as indicated by the name `customEVentName`.
142+
143+
And of course our parent component needs updating, like so:
144+
145+
```
146+
var app = new Vue({
147+
el: '#app',
148+
data: {
149+
person: {
150+
name: 'chris'
151+
}
152+
},
153+
methods: {
154+
method: () => {
155+
alert('called from component')
156+
}
157+
}
158+
})
159+
```
160+
161+
The interesting part happens when we invoke the method from the component itself, then it looks like this:
162+
163+
```
164+
Vue.component('person-detail',{
165+
template: `
166+
<div style="border: solid 1px blue">
167+
<button v-on:click="$emit('save', person)">Save</button>
168+
</div>`,
169+
props: ['person'],
170+
methods: {
171+
increment() {
172+
this.counter += 1 ;
173+
}
174+
}
175+
})
176+
```
177+
178+
### Actual example
179+
180+
Not how we below call our custom event `save`. We will soon see how this matches up in our component.
181+
182+
```
183+
<person-detail v-on:save="method" >
184+
```
185+
186+
Let's now turn to our component and look at how we can invoke the event we just set up:
187+
188+
```
189+
<button v-on:click="$emit('save', person)">Save</button>
190+
```
191+
192+
Zooming in we see `v-on:click` and that it invokes `$emit`.

Diff for: components/app.js

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
Vue.component('person-detail',{
2+
template: `
3+
<div style="border: solid 1px blue; padding: 30px; box-shadow: 0px 0px 5px gray">
4+
5+
Person object
6+
<input v-model="person.name" /> <br/>
7+
8+
Name:
9+
<input v-model="name" />
10+
11+
Person: {{person.name}}
12+
Counter: {{counter}}
13+
14+
<h2>Copy person</h2>
15+
<input v-model="copyPerson.name" />
16+
17+
<h2>Copy jedis</h2>
18+
<div v-for="jedi in copyJedis">
19+
{{ jedi.name }}
20+
<input v-model="jedi.name" />
21+
</div>
22+
23+
<h2>Jedis</h2>
24+
<div v-for="jedi in jedis">
25+
{{ jedi.name }}
26+
<input v-model="jedi.name" />
27+
</div>
28+
<input v-model="newJedi" />
29+
<button v-on:click="addJedi" >Add</button>
30+
31+
<h2>List</h2>
32+
<div v-for="item in list">
33+
{{ item.name }}
34+
<input v-model="item.name" />
35+
</div>
36+
<input v-model="newItem" />
37+
<button v-on:click="add" >Add</button>
38+
39+
<button v-on:click="increment">+</button>
40+
<button v-on:click="$emit('save', person)">Save</button>
41+
</div>`,
42+
props: ['person', 'counter', 'name', 'jedis'],
43+
methods: {
44+
increment() {
45+
this.counter += 1 ;
46+
},
47+
add() {
48+
this.list.push({ name: this.newJedi});
49+
this.newItem = "";
50+
},
51+
addJedi() {
52+
this.jedis.push({ name: this.newJedi});
53+
this.newJedi = "";
54+
}
55+
},
56+
data() {
57+
const copyJedis = this.jedis.map( j => Object.assign({},j));
58+
const copyPerson = Object.assign({}, this.person);
59+
60+
return {
61+
newJedi: '',
62+
newItem: '',
63+
list: [],
64+
copyJedis,
65+
copyPerson
66+
};
67+
}
68+
})
69+
70+
var app = new Vue({
71+
el: '#app',
72+
data: {
73+
message: 'Hello Vue!',
74+
person: {
75+
name: 'chris'
76+
},
77+
counter: 0,
78+
title: 'Star Wars',
79+
jedis: [{
80+
name: 'luke'
81+
},
82+
{
83+
name: 'vader'
84+
}]
85+
},
86+
methods : {
87+
// points to window this
88+
showDetail : (product) => {
89+
alert('detail ' + product.name);
90+
},
91+
// points to window this
92+
save: (person) => {
93+
alert('called from component');
94+
},
95+
// points to correct this, no =>
96+
changeTitle() {
97+
this.title = "new title";
98+
}
99+
}
100+
})

Diff for: components/index.html

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<html>
2+
3+
<body>
4+
<div id="app">
5+
{{ message }} {{person.name}} counter from parent: {{counter}}
6+
7+
<div v-once>{{title}}</div>
8+
<button v-on:click="changeTitle">Change title</button>
9+
10+
<div v-for="jedi in jedis">
11+
{{jedi.name}}
12+
</div>
13+
14+
<person-detail :jedis="jedis" :name="person.name" v-bind:counter="counter" v-on:save="save" :person="person">
15+
</div>
16+
<!-- development version, includes helpful console warnings -->
17+
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
18+
<script src="app.js"></script>
19+
</body>
20+
21+
</html>

Diff for: setup/README.md

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
introducing {}
2+
3+
`data` property is what we can show
4+
5+
```
6+
var app = new Vue({
7+
el: '#app',
8+
data: {
9+
message: 'Hello Vue!'
10+
}
11+
})
12+
13+
{{message}}
14+
```
15+
16+
This makes `message` available to template.
17+
Add another property like so:
18+
19+
```
20+
var app = new Vue({
21+
el: '#app',
22+
data: {
23+
message: 'Hello Vue!',
24+
secondmessage : 'Hello again'
25+
}
26+
})
27+
28+
{{secondmessage}}
29+
```

Diff for: setup/app.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var app = new Vue({
2+
el: '#app',
3+
data: {
4+
message: 'Hello Vue!',
5+
otherMessage: 'other message'
6+
}
7+
})

Diff for: setup/index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<html>
2+
3+
<body>
4+
<div id="app">
5+
{{ message }} {{ other message }}
6+
</div>
7+
<!-- development version, includes helpful console warnings -->
8+
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
9+
<script src="app.js"></script>
10+
</body>
11+
12+
</html>

0 commit comments

Comments
 (0)