本文是通过学习“慕课网”的Vue相关课程整理的Vue学习笔记,错误与不足之处欢迎大家批评指正~
课程连接
Vue官网
Vue官方文档 写的非常详细,有能力的小伙伴可以看看 : - )
vue
1. 安装Vue
- 源码形式
https://vuejs.org/js/vue.js复制Vue代码在工程中新建vue.js文件,粘贴,使用时通过标签引用即可。
HelloVue
新建index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue2.6</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">{{msg}}</div>
<script>
new Vue({
el:"#root",
data:{
msg:"hello Vue"
}
})
</script>
</body>
</html>

解释说明
- el 意为element标签,值代表和DOM中的那个id选择器中的元素进行绑定,绑定指定标签后,其标签的值便由Vue对象接管。
- data中的值即为标签中表示的值。
Vue实例,挂载点与模板
<div id="root">
<h1>Hello {{msg}}</h1>
</div>
<script>
new Vue({
el:"#root",
data:{
msg:"hello Vue"
}
})
</script>
- Vue通过el的值绑定指定的标签,该标签即为该Vue实例的挂载点
- 挂载点中的内容称之为模板,本例中,模板为
<h1>Hello {{msg}}</h1>
模板的内容也可以直接写到Vue实例中,通过template
属性进行表示,如下:
<div id="root">
</div>
<script>
new Vue({
el:"#root",
template:"<h1>Hello {{msg}}</h1>",
data:{
msg:"hello Vue"
}
})
</script>
两种模板效果相同

数据
<div id="root">
<h1>{{number}}</h1>
</div>
<script>
new Vue({
el:"#root",
data:{
msg:"hello Vue",
number:123
}
})
</script>
- 上面我们通过{{ 变量名}}的形式获取变量的值,该方式称之为插值表达式
- 除了插值表达式之外,我们可以通过vue提供的指令进行获取相关变量的值
-
<h1 v-text="number"></h1>
代表h1
中的内容由number属性表示,v-text
是vue中的一个指令,表示告诉h1
要显示的内容是number变量。 - 除了用
v-text
指令外,还可以使用v-html
,在本例中展示的效果都是一样的,但是如果变量的内容中包含HTML代码,v-text
原样显示,v-html
会将变量中的HTML代码进行渲染展示。
-
<div id="root">
<h1 v-html="content"></h1>
<h1 v-text="content"></h1>
</div>
<script>
new Vue({
el:"#root",
data:{
msg:"hello Vue",
number:123,
content:"<h1>hello</h1>"
}
})
</script>

事件&方法
- 功能1:为挂在点绑定事件,当鼠标点击数据的时候,触发
click
事件,并通过指定相关方法,改变挂载点的内容。
<div id="root">
<h1 v-on:click="handleClick">{{content}}</h1>
</div>
<script>
new Vue({
el:"#root",
data:{
msg:"hello Vue",
number:123,
content:"hello"
},methods:{
handleClick: function () {
this.content = "world"
}
}
})
</script>
- vue 提供
v-on
指令为挂载点绑定事件,v-on
可以简写为@
效果是一样的。 - 如果想执行指定的方法,在Vue实例中添加
methods
属性,添加相应方法即可。 - 更改挂载点的内容不用我们操作DOM,直接通过操作Vue实例即可操作content内容,即
this.xxx
1562632343680.png
- 功能2:为一个标签设置鼠标悬浮,鼠标在标签上停留时,出现提示。
通常我们直接可以在标签中加title
属性,之后设置title
属性的值即可,如下:
<div id="root">
<div title="Hello World">Hello World</div>
</div>
但是这样写无法更改title属性的值,我们应该把title属性的值交给Vue实例接管。
<div id="root">
<div v-bind:title="title">Hello World</div>
</div>
<script>
new Vue({
el:"#root",
data:{
title:"this is hello world"
}
})
</script>
-
v-bind
指令,使用v-bind
指令后,title的值不再是一个简单的字符串了,而办成了一个js表达式。v-bind
指令可以简写成:
即可
数据双向绑定
上面介绍的所有例子都是通过Vue实例控制标签中的内容,标签的内容却无法控制Vue实例中属性的值,即数据都是单向绑定
使用v-model
完成数据双向绑定。
<div id="root">
<input v-model="content">
<div>{{content}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
content:"this is a content"
}
})
</script>

我们更改input搜索框的值时,下面的div标签中的内容也随即发生了改变,即数据双向绑定
Vue的计算属性和侦听器
- 需求1:实现一个功能,在input搜索框中分别输入姓和名,在div标签中展示姓名。
通常我们实现该功能只需要通过Vue的v-model属性完成姓和名的数据绑定,然后在div搜索框中分别将姓和名的属性写进去即可。即:
<div id="root">
姓:<input v-model="firstName"/></br>
名:<input v-model="lastName">
<div>{{firstName}}{{lastName}}</div>
</div>
这样写也可以,但是首先代码可读性较差,而且如果多个地方都要展示姓名,都要
分别写姓和名,容易发生拼写错误以及代码冗余。Vue提供了‘计算属性’的概念。即编写一个函数,然后在div标签中接收函数的返回值即可。
<div id="root">
姓:<input v-model="firstName"/></br>
名:<input v-model="lastName">
<div>{{fullName}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstName:'',
lastName:''
},
computed:{
fullName:function () {
return this.firstName+""+this.lastName
}
}
})
</script>
使用Vue示例中的computed属性,后面编写相应的函数即可。

- 需求2:设计一个计数器,在每次更改input框中的值后,计数器的值加1
在Vue实例中添加watch
属性,为fullName 添加侦听器,每次fullName的值发生改变时,侦听器都会执行。
<div id="root">
...
<div>{{count}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
...
count:0
},
...
watch:{
fullName:function () {
this.count++
}
}
})
</script>

v-if,v-show,v-for
- 需求1:实现一个功能,页面中有一个div标签和一个按钮,点击按钮,div标签内容隐藏,再次点击按钮,div标签内容显示。
<div id="root">
<div v-if="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleClick:function () {
this.show = !this.show
}
}
})
</script>

除了使用
v-if
指令,还可以使用v-show
指令,显示的效果是相同的,但是使用v-if
指令,每次都会将div标签从DOM树中添加或者移除,使用v-show
指令vue则会每次会在div标签中添加display属性变成none或者清除该属性。
- 需求2:展示list中的值
<div id="root">
<ul>
<li v-for="item of list">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
list:[1,2,3]
}
})
</script>

为了增加渲染效率,我们可以每次
:key
属性,值得注意的是:key
属性的值不能是重复的,增强后的结果如下:
<ul>
<li v-for="(item,index) of list" :key="index">{{item}}</li>
</ul>
在遍历for循环的时候,每次获取item的下标index作为:key属性的索引。
牛到小试
动手实现一个todo-list
需求:页面有一个搜索框,在搜索框中输入内容,点击提交按钮,下面出现一个列表,列表中展示搜索框中内容。
思路:
- 使用v-model完成数据的双向绑定
- 为按钮添加点击事件,将搜索框中的内容添加到list中,并通过v-for遍历该集合。
<div id="root">
<div>
<input v-model="inputValue"/>
<button @click="onClick">提交</button>
</div>
<ul>
<li v-for="(item,index) of list" :key="index">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
inputValue:"",
list: []
},
methods:{
onClick:function () {
this.list.push(this.inputValue)
this.inputValue=null
}
}
})
</script>

组件
上面的例子中,<li>可能不仅在这里会使用,其他很多地方都可以引用,所以我们可以将<li>抽象成为一个“组件”。
- 全局组件
<div id="root">
...
<ul>
<todo-item></todo-item>
</ul>
</div>
<script>
Vue.component(
'todo-item',
{
template:'<li>item</li>'
})
...
</script>

定义的全局组件任何地方都可以使用。
- 局部组件
<script>
var TodoTtem={
template:'<li>item</li>'
}
})
</script>
该局部组件无法直接使用,会报没有注册该组件的异常。

使用局部组件时,我们要在需要使用的Vue实例中进行注册。如下:
<div id="root">
...
<ul>
<todo-item></todo-item>
</ul>
</div>
<script>
var TodoTtem={
template:'<li>item</li>'
}
new Vue({
el:"#root",
data:{
components:{
'todo-item:':TodoTtem
},
...
})
</script>
父组件给子组件传值
通过content
属性向子组件传值,子组件使用props
属性进行接收,如下:
<div id="root">
...
<ul>
<todo-item v-for="(item,index) of list"
:key="index"
:content="item"></todo-item>
</ul>
</div>
<script>
Vue.component(
'todo-item', {
props:['content'],
template:'<li>{{content}}</li>'
});
...
})
</script>
解释:使用v-for
遍历list集合,每次将遍历的元素通过content
传递给todo-list
组件,todo-list
组件通过使用props
属性接收content传递过来的值,并通过提前定义好的模板进行渲染。
子组件向父组件通信
在Vue中,子组件向父组件通信采用“发布订阅”模式,即设计模式中的观察者模式,还不了解的小伙伴可以百度一下。
需求:鼠标点击列表中的元素后,该元素被删除。
分析:列表中的元素是父组件中list列表中的元素,要想删除父组件中list列表中的元素,我们要通知父组件删除指定索引的元素。父组件进行删除即可。
具体实现:
- 在子组件的每一个列表上注册鼠标点击事件。
- 点击事件触发后,子组件向父组件通信,并告知父组件要删除列表中具体哪个元素的索引。
- 父组件监听子组件的消息,接收到子组件传递过来的消息后,触发删除函数,删除列表中指定的元素。
代码如下:
<div id="root">
<div>
<input v-model="inputValue"/>
<button @click="onClick">提交</button>
</div>
<ul>
<todo-item v-for="(item,index) of list"
:key="index"
:content="item"
:index="index"
@delete="handleDelete"
></todo-item>
</ul>
</div>
<script>
Vue.component(
'todo-item', {
props:['content','index'],
template:'<li @click="handleClick">{{content}}</li>',
methods:{
handleClick:function () {
this.$emit('delete',this.index)
}
}
});
new Vue({
el:"#root",
data:{
inputValue:"",
list: []
},
methods:{
onClick:function () {
this.list.push(this.inputValue)
this.inputValue=null
},
handleDelete:function (index) {
this.list.splice(index,1)
}
}
})
</script>

Vue Cli 脚手架工具
Vue Cli 帮助我们构建大型项目的开发目录,提供了webpack打包的配置等,大大简化了除了开发上的大部分问题。
Vue Cli 的安装和使用
- 安装Vue Cli
# 全局安装vue-cli
$ npm install --global vue-cli
- 使用Vue Cli构建项目
- webpack为项目的模板名称
- my-project为自己的项目名称
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project

- 进入项目的根目录, 启动项目
$ npm run dev

-
访问localhost:8080
image.png
模板结构

代码解读
- index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>todolist</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
只有一个div标签,注意该标签的id=“app”
- 打开main.js文件
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
main.js创建了一个Vue实例,设置"app"为挂载点。并引入App组件。
- 打开App.vue
该文件就是一个完整的组件,包含模板,逻辑,样式。
<template>
...
</template>
<script>
...
</script>
<style>
...
</style>
看到这,我们便明白了该模板的工作原理。
使用模板重写todo-list
- App.vue
<template>
<div>
<input v-model="inputValue"/>
<button @click="handlerSubmit">提交</button>
<ul>
<todo-item
v-for="(item,index) of list"
:key="index"
:msg="item"
:index="index"
@delete="handleDelete"
></todo-item>
</ul>
</div>
</template>
<script>
import TodoItem from './components/HelloWorld'
export default {
name: 'App',
components: {
'todo-item': TodoItem
},
data: function () {
return {
inputValue: null,
list: []
}
},
methods: {
handlerSubmit: function () {
this.list.push(this.inputValue)
this.inputValue = null
},
handleDelete: function (index) {
this.list.splice(index, 1)
}
}
}
</script>
<style>
</style>
- HelloWorld.vue
<template>
<div>
<input v-model="inputValue"/>
<button @click="handlerSubmit">提交</button>
<ul>
<todo-item
v-for="(item,index) of list"
:key="index"
:msg="item"
:index="index"
@delete="handleDelete"
></todo-item>
</ul>
</div>
</template>
<script>
import TodoItem from './components/HelloWorld'
export default {
name: 'App',
components: {
'todo-item': TodoItem
},
data: function () {
return {
inputValue: null,
list: []
}
},
methods: {
handlerSubmit: function () {
this.list.push(this.inputValue)
this.inputValue = null
},
handleDelete: function (index) {
this.list.splice(index, 1)
}
}
}
</script>
<style>
</style>
执行npm run dev
浏览器访问localhost:8080:

网友评论