Vue.js小白入门

实例化Vue对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div id="app1">
<h1>{ { name } }</h1>
<p>{ { job } }</p>
<p>{ { sayHi("methods 方法") } }</p>
<a :href="website">logan个人博客</a><br>
<p v-html="websiteTag"></p> <br>
<button @click = "greet">欢迎</button>
</div>

<script>
var app1 = new Vue({
el : "#app1",
data : {
name : "logan",
job : "fronted enginner",
website : "http://xutianshi.top",
websiteTag : "<a href='http://xutianshi.top'>v-html</a>"
},
methods : {
greet: function(){
alert("Hello Vue!")
},
sayHi : function(txt){
return "hello " + this.name + " ! " + txt
}
}
})
</script>

事件及事件修饰符

  • .stop 阻止冒泡
  • .prevent 阻止默认行为
  • .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
  • .self 只当在 event.target 是当前元素自身时触发处理函数,即事件不是从内部元素触发的
  • .once 事件将只会触发一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div id="app2">
<h1>Event</h1>
<p>I am { { age } } years old.</p>
<button @click="addAge(1)">大一岁</button>
<button @click="reduceAge(1)">小一岁</button>
<button @dblclick="addAge(10)">双击大十岁</button>
<button @dblclick="reduceAge(10)">双击小十岁</button>
<div id="canvas" @mousemove="updateXY">{ { x } },{ { y } } - <span id="stopMoving" @mousemove.stop>Stop Moving</span></div>
<a href="http://xutianshi.top" @click.prevent>logan个人博客</a>
</div>

<script>
var app2 = new Vue({
el : "#app2",
data : {
age : 25,
x : 0,
y : 0
},
methods : {
addAge : function(num){
this.age += num
},
reduceAge : function(num){
this.age -= num
},
updateXY : function(event){
this.x = event.offsetX;
this.y = event.offsetY;
}
}
})
</script>

键盘事件、按键修饰符及系统修饰键

全部的按键别名:

  • .enter
  • .tab
  • .delete (捕获“删除”和“退格”键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

系统修饰键

  • .ctrl
  • .alt
  • .shift
  • .meta

事件触发时修饰键必须处于按下状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="app3">
<h1>键盘 Event</h1>
<label for="">姓名:</label>
<input type="text" @keyup="logName">
<label for="">年龄:</label>
<input type="text" @keyup.enter="logAge">
</div>

<script>
var app3 = new Vue({
el : "#app3",
data : {

},
methods : {
logName : function(){
console.log("你正在输入名字")
},
logAge : function(){
console.log("你正在输入年龄")
}
}
})
</script>

双向数据绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="app4">
<h1>双向数据绑定</h1>
<label for="">姓名:</label>
<input type="text" @keyup="logName" ref="name" placeholder="edit me">
<span>{ { name } }</span>
<label for="">年龄:</label>
<input type="text" v-model="age" placeholder="edit me">
<span>{ { age } }</span>
</div>

<script>
var app4 = new Vue({
el : "#app4",
data : {
name : "",
age : ""
},
methods : {
logName : function(){
this.name = this.$refs.name.value
console.log("你正在输入名字")
}
}
})
</script>

计算属性computed

  • computed 计算属性是基于它们的依赖进行缓存的。

  • methods 每当触发重新渲染时,调用方法将总会再次执行函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div id="app5">
<h1>计算属性 Computed</h1>
<button @click="a++">Add to A</button>
<button @click="b++">Add to B</button>
<p>A - { { a } }</p>
<p>B - { { b } }</p>
<p>Age + A = { { AgeA } }</p>
<p>Age + B = { { AgeB } }</p>
</div>

<script>
var app5 = new Vue({
el : "#app5",
data : {
a : 0,
b : 0,
age : 35
},
computed : {
AgeA : function(){
return this.age + this.a
},
AgeB : function(){
return this.age + this.b
}
}
})
</script>

Class 与 Style 绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app6">
<h1>动态 CSS Class</h1>
<h2 :class="{ color:changeColor, length:changeLength }" :style="styleObject" @click="changeColor=!changeColor">示例1</h2>
<h2>示例2</h2>
</div>

<script>
var app6 = new Vue({
el : "#app6",
data : {
changeColor : false,
changeLength : false,
styleObject : {
border : "1px solid #000"
}
}
})
</script>

v-if 条件渲染

v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app7">
<h1>v-if 条件</h1>

<button @click="error = !error" >Toggle error</button>
<button @click="success = !success">Toggle success</button>
<button @click="isShow = !isShow">Toggle isShow</button>

<p v-if="error">Now you can see me(v-if) (error = true)</p>
<p v-else-if="success">Now you can see me(v-else-if) (success = true && error = false)</p>
<p v-else>Now (error and success) = false</p>
<p v-show="isShow">Now you can see me(v-show) (isShow = true)</p>
</div>

<script>
var app7 = new Vue({
el : "#app7",
data : {
error : false,
success : false,
isShow: false
}
})
</script>

v-for 列表渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="app8">
<h1>{ { title } }</h1>

<ul>
<li v-for="character in characters">名字:{ { character } }</li>
</ul>
<ul>
<li v-for="(user,index) in users">{ { index + 1 + "." } } 名字:{ { user.name } } &nbsp;&nbsp;年龄:{ { user.age } }</li>
</ul>

<template v-for="(user,index) in users">
<p>{ { index + 1 } } . { { user.name } }</p>
<p>{ { user.age } }</p>
</template>

<template v-for="user in users">
<ul>
<li v-for="(value,key,index) in user">{ { index } }-{ { key } }-{ { value } }</li>
</ul>
</template>
</div>

<script>
var app8 = new Vue({
el : "#app8",
data : {
characters : ["logan","leo","nancy"],
users : [
{ name:"henry",age:"25" },
{ name:"jack",age:"20" },
{ name:"tom",age:"23" }
],
title : "v-for 循环"
}
})
</script>

实战DEMO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 根容器 -->
<div id="vue-app">
<!-- 图片容器,根据ended的变化动态改变class -->
<div id="bag" :class="{ broken: ended }"></div>
<!-- 进度条容器,根据progress变化动态改变红条长度 -->
<div id="progress">
<div :style="{ width: progress + '%' }"></div>
</div>
<!-- 按钮组,点击减少/重置progress -->
<div id="btn-group">
<button @click="punch" v-show="!ended">可劲儿砸</button>
<button @click="restart">重新开始</button>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var vm = new Vue({ 
el : "#vue-app",
data : {
progress : 100,
ended : false
},
methods : {
punch : function(){
this.progress -= 10;
if (this.progress <= 0) {
this.ended = true;
}
},
restart : function(){
this.progress = 100;
this.ended = false;
}
}
})

初始化多个Vue对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="app9">
<h1>初始化多个Vue实例对象</h1>
<button @click="changeTitle">改变v-for标题</button>
</div>

<script>
var app9 = new Vue({
el : "#app9",
data : {

},
methods : {
changeTitle :function(){
app8.title = "已经改名了";
}
}
})
</script>

初始Vue组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div id="app10">
<greeting></greeting>
<greeting></greeting>
</div>

<script>
Vue.component("greeting",{
template : `<p>
{ { name } },初识Vue组件(模板)
<button @click="changeName">改名</button>
</p>`,
data : function(){
return {
name : "Logan"
}
},
methods : {
changeName : function(){
if (this.name == "Logan") {
this.name = "Lee"
} else {
this.name = "Logan";
}
}
}
})

var app10 = new Vue({
el : "#app10"
})
</script>

Vue - 搭建脚手架CLI

Vue-CLI 脚手架

  • 脚手架是通过webpack搭建的开发环境
  • 使用ES6语法
  • 打包和压缩js为一个文件
  • 项目文件在环境中编译,而不是浏览器
  • 实现页面自动刷新

搭建过程

1
2
3
4
5
6
7
8
# 全局安装 vue-cli
$ npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
# 安装依赖,走你
$ cd my-project
$ npm install
$ npm run dev

介绍SRC文件流程及根组件APP

  • assets文件夹:存放图片
  • components文件夹:存放组件
  • App.vue:根组件
  • main.js:
  • index.html:入口文件

index.html => main.js => App.vue => HelloWorld.vue

Vue 组件嵌套

全局注册嵌套

1
2
3
4
// 在main.js内
import Users from './components/Users'
// 全局注册组件
Vue.component('users',Users)

局部注册嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 在App.vue内
<script>
// 引入组件
import Users from './components/Users'

export default {
name: 'App',
data(){
return {
msg : '这是我的第一个Vue脚手架'
}
},
// 注册组件,将只在父组件模板中可用
components : {
users : Users
}
}
</script>

组件 CSS 作用域

<style scoped>

scoped表示限制CSS只在自身组件内起作用

不加scoped则各组件通用此组件的样式

实战DEMO2

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- 1模板:html结构 -->
<template>
<div id="app">
<app-header></app-header>
<users></users>
<app-footer></app-footer>
</div>
</template>

<!-- 2行为:处理逻辑 -->
<script>
import Users from './components/Users'
import Header from './components/Header'
import Footer from './components/Footer'

export default {
name: 'App',
data(){
return {
msg : '这是我的第一个Vue脚手架'
}
},
components : {
'users' : Users,
'app-header' : Header,
'app-footer' : Footer
}
}
</script>

Users.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
<div class="users">
<ul>
<li v-for="user in users" @click="user.show = !user.show">
<h2>{ { user.name } }</h2>
<h3 v-show="user.show">{ { user.position } }</h3>
</li>
</ul>
</div>
</template>

<style scoped>
.users{
width: 100%;
max-width: 1200px;
margin: 40px auto;
}
ul{
padding: 0;
display: flex;
flex-wrap: wrap;
}
li{
flex-grow: 1;
flex-basis: 200px;
padding: 40px 0;
margin: 20px;
border: 1px solid #222;
box-sizing: border-box;
text-align: center;
list-style: none;
}
</style>

属性传值Props(父To子)

  • 先在父组件内定义要传的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
data(){ 
return {
users : [
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false },
{ name : 'Logan', position : 'Fronted Enginner', show : false }
]
}
},
  • 在父组件内插入子组件的地方传入值
1
2
3
4
5
6
7
<template>
<div id="app">
<app-header></app-header>
<users :users="users"></users>
<app-footer></app-footer>
</div>
</template>
  • 在子组件内通过props传值
1
2
3
4
5
6
7
8
9
export default { 
name: 'users',
props : ['users'],
data: function(){
return {

}
}
}
  • prop验证(推荐写法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default { 
name: 'users',
props : {
users : {
type : Array,
required : true
}
},
data: function(){
return {

}
}
}

传值和传引用

传值:(Number,String,Boolean),在子组件内对其进行改变时,其他组件内不会发生变化

传引用:(Array,Object),在子组件内对其进行改变时,其他组件内会发生变化

不应该在子组件内部改变 prop。正确做法是

  • Prop 作为初始值传入后,子组件想把它当作局部数据来用
1
2
3
4
5
// 定义一个局部变量,并用 prop 的值初始化它:
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
  • rop 作为原始数据传入,由子组件处理成其它数据输出。
1
2
3
4
5
6
7
// 定义一个计算属性,处理 prop 的值并返回:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}

事件传值(子To父)

  • 第一步:在子组件内触发事件
1
2
3
4
5
6
7
8
9
10
11
12
<template>
<header>
<h1 @click="changeTitle">{ { tittle1 } } { { title } }</h1>
</header>
</template>

methods : {
changeTitle : function(){
// 在子组件内触发事件
this.$emit('titleChanged','通过事件子传父')
}
}
  • 第二步:在父组件内接受事件及参数
1
2
3
4
5
6
7
8
<template>
<div id="app">
<!-- 在父组件内接受事件及参数 -->
<app-header :title="title" @titleChanged="changeTitleFn($event)"></app-header>
<users :users="users"></users>
<app-footer :title="title"></app-footer>
</div>
</template>
  • 第三步:在父组件内定义事件函数
1
2
3
4
5
methods : { 
changeTitleFn : function(title){
this.title = title
}
}

生命周期(钩子函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>

<div id="app">
<p>{ { message } }</p>
</div>

<script type="text/javascript">

var app = new Vue({
el: '#app',
data: {
message : "xuxiao is boy"
},
beforeCreate: function () {
console.group('beforeCreate 创建前状态===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message)
},
created: function () {
console.group('created 创建完毕状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 挂载前状态===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 挂载结束状态===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
updated: function () {
console.group('updated 更新完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed: function () {
console.group('destroyed 销毁完成状态===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
</script>
</body>
</html>

create 和 mounted 相关

咱们在chrome浏览器里打开,F12看console就能发现

  • beforecreated:el 和 data 并未初始化
  • created:完成了 data 数据的初始化,el没有
  • beforeMount:完成了 el 和 data 初始化
  • mounted :完成挂载

beforeMount阶段el还是 { { message } },这里就是应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了。到后面mounted挂载的时候再把值渲染进去。

mounted内的方法执行完后页面显示

update 相关

数据发生改变时,将会触发update的操作。

updated内的方法执行完后更新内容显示

destroy 相关

执行了destroy操作,原先生成的dom元素还存在,但是后续DOM就不再受vue控制了。

路由和HTTP

路由

1.路由的安装

1
npm install vue-router

2.在main.js中安装路由功能

1
2
3
import VueRouter from 'vue-router'

Vue.use(vueRouter)

3.配置路由

1
2
3
4
5
6
const router = new VueRouter({ 
routes : [
{ path:'/',component:Home }
{ path:'/helloworld',component:HelloWorld }
]
})

4.引入组件

1
2
import HelloWorld from './comonents/HelloWorld'
import Home from './comonents/Home'

5.创建挂载根实例

1
2
3
4
5
6
7
/* eslint-disable no-new */
new Vue({
router,
el: '#app',
components: { App },
template: '<App/>'
})

6.添加html结构

1
2
3
4
5
<template>
<div id="app">
<router-view></router-view>
</div>
</template>

7.去除路径中#号

在main.js中router实例中配置

1
2
3
4
5
6
7
const router = new VueRouter({ 
routes : [
{ path:'/',component:Home },
{ path:'/helloworld',component:HelloWorld }
],
mode : 'history'
})

8.加入<router-link>导航

1
2
3
4
5
6
7
8
9
<template>
<div id="app">
<ul>
<li><router-link to="/">Home</router-link></li>
<li><router-link to="/helloworld">Hello</router-link></li>
</ul>
<router-view></router-view>
</div>
</template>

http

使用vue-resource

1.安装vue-resource

1
npm install vue-resource --save-dev

2.在main.js中安装

1
2
3
import VueResource from 'vue-resource'

Vue.use(VueResource)

3. Home.vue中添加created钩子函数 请求http

1
2
3
4
5
6
created(){ 
this.$http.get('http://jsonplaceholder.typicode.com/users').then((data) => {
// console.log(data)
this.users = data.body
})
}

4.在user.vue中添加html结构

1
2
3
4
5
6
7
8
9
10
<template>
<div class="users">
<ul>
<li v-for="user in users" >
<h2>{ { user.name } }</h2>
<h3>{ { user.email } }</h3>
</li>
</ul>
</div>
</template>
文章目录
  1. 1. 实例化Vue对象
  2. 2. 事件及事件修饰符
  3. 3. 键盘事件、按键修饰符及系统修饰键
  4. 4. 双向数据绑定
  5. 5. 计算属性computed
  6. 6. Class 与 Style 绑定
  7. 7. v-if 条件渲染
  8. 8. v-for 列表渲染
  9. 9. 实战DEMO
  10. 10. 初始化多个Vue对象
  11. 11. 初始Vue组件
  12. 12. Vue - 搭建脚手架CLI
  13. 13. 介绍SRC文件流程及根组件APP
  14. 14. Vue 组件嵌套
    1. 14.1. 全局注册嵌套
    2. 14.2. 局部注册嵌套
  15. 15. 组件 CSS 作用域
  16. 16. 实战DEMO2
  17. 17. 属性传值Props(父To子)
  18. 18. 传值和传引用
  19. 19. 事件传值(子To父)
  20. 20. 生命周期(钩子函数)
  21. 21. 路由和HTTP
    1. 21.1. 路由
    2. 21.2. http
|