Vue初始搭建与基础知识--潘登同学的前端笔记
搭建Vue环境
1.安装vuecli工具
cnpm install -g @vue/cli
2.创建项目
vue create my-project
3.运行项目
要在cd my-project
下才能创建
npm run serve
4.注意事项
node_modules 文件特别大,上传项目到git上的时候,可以先把他删除,因为别人可以通过安装把文件下载回来
public是主目录
src是源码文件
.browserslistrc是配置文件
.gitignore是github的忽略文件
babel.config.js是ES6的babel配置文件
package.json也是配置文件
Vue的基础知识
模板语法
- Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
插值
- 双大括号(输出的是文本)
<p>{{ msg }}</p>
- 如果想储存原始html代码,需要加上
<p v-html="price"></p>
所以所有通过v-开头的都被称为指令
- 绑定属性 v-bind:+属性
<div v-bind:id="dynamicId"></div>
- JS语法限制
在双大括号只能包含单行表达式(可以有一些运算或者判断)
指令
- 所以所有通过v-开头的都被称为指令,指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
<p v-if="seen">现在你看到我了</p>
这里,v-if
指令将根据表达式 seen
的值的真假来插入/移除 <p>
元素。
- 参数:一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML attribute:
<a v-bind:href="url">...</a>
在这里 href
是参数,告知 v-bind
指令将该元素的 href
attribute
与表达式 url
的值绑定。
- 另一个例子是
v-on
指令,它用于监听 DOM 事件:
<a v-on:click="doSomething">...</a>
缩写
v-bind
可以缩写为:
v-on
可以缩写为@
计算属性和侦听器
计算属性
下列代码不易于维护且不易复用
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
可以尝试改为
<div id="example">
{{ reversedMessage }}
</div>
// 在于data() 同级的水平下
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
计算属性缓存 vs 方法
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
侦听器
watch
方法会响应数据的变化,当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<!-- 来设置一个输入框 在改变输入的时候会返回新旧两个值 -->
<div>
<input type="text" name="" id="" v-model="nick">
</div>
// 与data() 同级下,当然不要忘记在data声明nick
watch:{
// 监听的方法名称必须等于属性名
nick(newValue,oldValue,){
console.log(newValue,oldValue);
},
}
Class 与 Style 绑定
绑定 HTML Class
- 对象语法
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示 active
这个 class
存在与否将取决于数据 property isActive
可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class
指令也可以与普通的 class attribute 共存。当有如下模板:
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
data: {
isActive: true,
hasError: false
}
绑定的数据对象不必内联定义在模板里,也可以通过对象方式
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
还可以绑定一个计算属性来操作
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
- 数组语法
v-bind:style
的数组语法可以将多个样式对象应用到同一个元素上:
(可以在数组中嵌套对象)
<div v-bind:style="[baseStyles, overridingStyles]"></div>
条件渲染
v-if
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true
值的时候被渲染。可以加入else
<p v-if="flag">我出来啦</p>
<p v-else>我不见啦</p>
在 <template>
元素上使用 v-if
条件渲染分组
- 因为
v-if
是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个<template>
元素当做不可见的包裹元素,并在上面使用v-if
。最终的渲染结果将不包含<template>
元素。
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
v-else-if
- 顾名思义,充当
v-if
的“else-if 块”,可以连续使用:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
v-show
- 另一个用于根据条件展示元素的选项是
v-show
指令。用法大致一样:
<h1 v-show="ok">Hello!</h1>
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS property display
注意
v-show
不支持 <template>
元素,也不支持 v-else
v-if
与 v-show
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。(元素删除和添加)v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。- 一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
列表渲染
用 v-for
把一个数组对应为一组元素
- 我们可以用
v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。
<ul id="example-1">
<li v-for="item in items" :key="item.message">
{{ item.message }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
- 在
v-for
块中,我们可以访问所有父作用域的 property。v-for
还支持一个可选的第二个参数,即当前项的索引。
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
- 在
v-for
里使用值范围:v-for
也可以接受整数。在这种情况下,它会把模板重复对应次数。
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
在 v-for
里使用对象
- 可以用
v-for
来遍历一个对象的 property。
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
- 也可以提供第二个的参数为 property 名称 (也就是键名):
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
- 还可以用第三个参数作为索引:
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
注意
在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
数组更新检测
变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:(其他的方法(非变更方法,就是不改变原对象,只是返回新对象的操作)就不好用了)
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
<div>
<h3>list渲染</h3>
<button @click="addItemHandle">添加数据</button>
<ul>
<li @click="getMessageHandle(item.text)" v-for="(item, index) in result" :key="item.id">
{{ item.text }}-{{ index }}
</li>
</ul>
<a @click.prevent="clickPD" href="https://pd3nbplus.github.io/">pd的个人博客</a>
</div>
addItemHandle(){
this.result.push({id:1004, text: "四川的锤子"});
}
非变更方法
- filter() 过滤函数
- concat() 合并多个数组 返回新数组 不改变原数组
- slice() 数组切片
但也有解决方案(效果与上面一样)
addItemHandle(){
this.result = this.result.concat({id:1004, text: "四川的锤子"});
}
在 <template>
上使用 v-for
- 类似于
v-if
,你也可以利用带有v-for
的<template>
来循环渲染一段包含多个元素的内容。
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for
与 v-if
一同使用
注意
我们不推荐在同一元素上使用 v-if
和 v-for
- 当它们处于同一节点,
v-for
的优先级比v-if
更高,这意味着v-if
将分别重复运行于每个v-for
循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
- 而如果你的目的是有条件地跳过循环的执行,那么可以将
v-if
置于外层元素 (或<template>
) 上。如:
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>
事件处理
监听事件
- 可以用
v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})
事件处理方法
- 许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在
v-on
指令中是不可行的。因此v-on
还可以接收一个需要调用的方法名称。
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
内联处理器中的方法
- 除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
- 有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量
$event
把它传入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
new Vue({
el: '#example-3',
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
})
事件修饰符(阻止默认事件,冒泡)
- 在事件处理程序中调用
event.preventDefault()
或event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js
为 v-on
提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
- .once
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 不跳转 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
注意
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self
会阻止所有的点击,而 v-on:click.self.prevent
只会阻止对元素自身的点击。
注意
不要把 .passive
和 .prevent
一起使用,因为 .prevent
将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive
会告诉浏览器你不想阻止事件的默认行为。
按键修饰符
- 在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为
v-on
在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
- 可以直接将
KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input v-on:keyup.page-down="onPageDown">
系统修饰键
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
- .ctrl
- .alt
- .shift
- .meta(window徽标)
<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>
注意
请注意修饰键与常规按键不同,在和 keyup
事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl
的情况下释放其它按键,才能触发 keyup.ctrl
。
- .exact 修饰符
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>
鼠标按钮修饰符
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
- .left
- .right
- .middle
表单输入与绑定
基础用法
- 可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意
v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值。
v-model
在内部为不同的输入元素使用不同的 property
并抛出不同的事件:
- text 和 textarea 元素使用
value
property 和input
事件; - checkbox 和 radio 使用
checked
property 和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
<!-- 简单输入框 加入lazy参数:不是实时获取而是失去焦点才获取-->
<input v-model.lazy="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<!-- 多行文本 -->
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
<!-- 单个复选框,绑定到布尔值: -->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
<!-- 对于多个复选框 结合下面的JS -->
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
data: {
checkedNames: []
}
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步:(如失去焦点,或者回车键)
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符
<input v-model.trim="msg">
/label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
data: {
checkedNames: []
}
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步:(如失去焦点,或者回车键)
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符
<input v-model.trim="msg">