1、数据与方法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{a}}
</div>
<script type="text/javascript">
let data = {a: 1}
/*将data对象绑定到vm中*/
let vm = new Vue({
el: "#app",
data: {
/*这种方式是传入键值对-->JSON对象*/
message111: "hello,vue"
},
/*这种方式是传入JSON对象*/
data,
});
vm.a = 222
data.a = 333
/*从vm中获取实例的方法,也就是说明通过$可以获取实例对象*/
alert(vm.$data === data)// => true
alert(vm.$el === document.getElementById("app"))// => true
</script>
</body>
</html>
2、实例生命周期钩子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
/*每个vue实例在被创建时都要经历一系列的初始化过程。例如:需要设置数据监听
* 编译模板,将实例new vue挂在到DOM,el:#app并在数据变化时更新DOM*/
/*
* create钩子函数可以用来在一个实例被创建之后执行代码
* mounted
* updated
* destroyed
* */
new Vue({
data: {
message: "hello"
},
create: function (){
console.log("执行create钩子函数"+this.message)
}
})
</script>
</body>
</html>
02、模板方法
1、插值-文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello"
}
})
</script>
</body>
</html>
2、插值-原始HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>Using mustaches</p>
<p>Using v-html directive</p>
<p v-html="rowHtml"></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello"
},
methods: {
rowHtml: function (){
console.log("hello")
}
}
})
</script>
</body>
</html>
3、插值-attribute
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-bind:id="dynamicId"/>
<button v-bind:disabled="isButtonDisable"/>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
dynamicId: "test"
},
/*计算属性,使用的时候不带括号*/
computed: {
isButtonDisable: function (){
return false;
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--JavaScript表达式-->
{{!booleanTrue}}<br/>
{{message.split(" ").reverse()}}
</div>
<!--迄今为止 ,我们一直绑定简单得到property键值,但实际上,对于所有的数据绑定,vue都提供了完全额的JavaScript表达式支持-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
booleanTrue: true,
message: "hello wwj"
}
})
</script>
</body>
</html>
5、指令-参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--href是参数,告知v-bind指令将该元素的href属性与表达式URL的值绑定-->
<a v-bind:href="url"></a>
<a v-on:click="doSomething()" v-bind:href="url">点我啊</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
url: "https://www.baidu.com/"
},
methods: {
doSomething: function (){
alert("DOM绑定点击事件")
}
}
})
</script>
</body>
</html>
6、指令-动态参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--相当于v-bind:click-->
<a v-bind:[attributeName2]="doSomething" v-bind:[attributeName1]="url">吊我啊</a>
<p>{{attributeName1}}</p>
</div>
<!--从2.60开始,可以用方括号括起来的JavaScript表达式作为一个指令的参数-->
<!--对动态参数的要求:
动态参数预期会求出一个字符串,异常情况下为null,其他非字符串类型的值都会触发一个警告
空格、引号放在attribute中是无效的
避免使用大小写来区别键值,因为浏览器会将attribute全部转换成小写-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
url: "https://www.baidu.com/",
attributeName1: "href",
attributeName2: "click"
},
methods: {
doSomething: function (){
alert("DOM绑定点击事件")
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<a v-on:[attributeName2]="doSomething()" v-bind:[attributeName1]="url">点我啊</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
url: "https://www.baidu.com/",
attributeName1: "href",
attributeName2: "click"
},
methods: {
doSomething: function (){
alert("DOM绑定点击事件")
}
}
})
</script>
</body>
</html>
7、指令-修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<form v-on:submit.prevent="onsubmit">
</form>
</div>
<!--修饰符是以半角句号“.”,指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如
.prevent修饰符告诉v-on指令对于触发的事件调用event.preventDefault()-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
})
</script>
</body>
</html>
8、缩写-v-bind
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 完整语法 -->
<a v-bind:href="url" v-on:click="doThis()">点我啊</a>
<!-- 缩写 -->
<a :href="url">点我啊</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="key"> 点我啊 </a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
key: "href",
url: "https://www.baidu.com"
},
computed: {
doThis: function (){
alert("恭喜你")
}
}
})
</script>
</body>
</html>
9、缩写-v-on
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
event: "click"
}
})
</script>
</body>
</html>
03、计算属性和侦听器
1、计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--JavaScript表达式-->
<!-- {{message.split(" ").reverse()}}-->
<!--通过计算属性实现-->
{{ message1 }}
</div>
<!--模板内的表达式非常遍历,但是设计它们的初衷是用于简单的运算的。
在模板内使用太多的逻辑会让模板过于笨重且难以维护,看上面的表达式便可看出
想想模板中有很多这种表达式,那么将非常难以维护,这时候计算属性便出场了,
该属性具备了计算属性,也就是逻辑处理能力,就像函数一样,不过我们使用的时候把它当做属性对待-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
},
computed: {
message1: function (){
return this.message.split(" ").reverse()
}
}
})
</script>
</body>
</html>
2、计算属性缓存VS方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
计算属性翻转字符串:{{message3}}<br/>
通过方法翻转字符串:{{message()}}
</div>
<!--计算属性和方法的不同
计算属性是基于他们的响应式依赖进行缓存的,只有相关依赖的值变化时才会重新求值显然这样的好处便是提高了响应的效率
而通过方法,每次调用都需要执行,显然在一定程度上会降低响应的消息-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message1: "hello vue",
message2: "hello vue"
},
computed: {
message3: function (){
return this.message1.split(" ").reverse()
}
},
methods: {
message: function (){
return this.message2.split(" ").reverse()
}
}
})
</script>
</body>
</html>
3、计算属性VS侦听器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{fullName}}
</div>
<!--vue提供了一种更通用的方式来观察和响应vue实例上的数据变动:侦听属性。
当一些数据需要随着其他数据变动而变化时,很容易滥用watch-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
firstName: "Foo",
lastName: "Bar",
fullName: "Foo Bar"
},
/*侦听数据的方式检查数据的变动*/
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
},
/*计算属性的方式检查数据的变动*/
computed: {
fullName: function (){
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
</html>
4、计算属性的setter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{fullName}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue",
firstName: "Foo",
lastName: "Bar",
fullName: "Foo Bar"
},
computed: {
fullName: {
get: function (){
return this.firstName+" "+this.lastName
},
set: function (newValue){
let names = newValue.split(" ")
this.firstName = names[0]
this.lastName = names[names.length-1]
}
}
}
})
</script>
</body>
</html>
5、侦听器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
question: '',
answer: 'I cannot give you an answer until you ask q question'
},
watch: {
question: function (newQuestion,oldQuestion){
this.answer = "waiting for you to stop typing"
this.debouncedGetAnswer()
},
created: function () {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
const vm = this;
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
</body>
</html>
04、Class与Style
1、绑定HTML-对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--该class的存在与否取决与数据property isActive的取值-->
<div v-bind:class="{active: isActive}">大王叫我来巡山</div>
<!--可以给class传入多个参数达到切换class的作用-->
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }">师娘叫我去买衣服</div>
<!--将这些参数封装在一个对象中-->
<div v-bind:class="classObject">师娘叫我去买衣服</div>
<!--也可以通过计算属性给class赋值-->
<div v-bind:class="classObject">师娘叫我去买衣服</div>
</div>
<!--可以传给v-bind:class一个对象,以动态地转换class-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
isActive: true,
hasError: false,
classObject: {
active: true,
'text-danger': false
}
},
computed: {
classObject: function (){
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
})
</script>
</body>
</html>
2、绑定HTML-数组用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--可以把数组传给v-bind:class,以应用一个class列表-->
<div v-bind:class="[activeClass, errorClass]"></div>
<!--上面的样式将会被渲染成下面这样-->
<div class="active text-danger"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
activeClass: "active",
errorClass: "text-danger"
}
})
</script>
</body>
</html>
3、绑定HTML-用在组件上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--可以添加一些class-->
<my-component class="boo too"></my-component>
<!--可以带数据绑定class-->
<my-component v-bind:class="xoo"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component("my-component",{
template: '<p class="foo bar">自定义组件</p>'
})
let vm = new Vue({
el: "#app",
data: {
xoo: "too"
}
})
</script>
</body>
</html>
4、绑定内联样式-对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-bind:style="{color: 'red',fontSize: '18px'}">将样式直接通过大括号绑定</div>
<div v-bind:style="styleObject">将样式通过data对象进行绑定</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
styleObject: {
color: "red",
fontSize: "18px"
}
}
})
</script>
</body>
</html>
5、绑定内联样式-数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-bind:style="[baseStyles,overridingStyles]">样式通过数组绑定样式</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
baseStyles: {
color: 'red',
fontSize: '18px'
},
overridingStyles: {
color: 'red',
fontSize: '18px'
}
}
})
</script>
</body>
</html>
6、绑定内联样式-自动添加前缀
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
</div>
<!--当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀。-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
7、绑定内联样式-多重值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。-->
<div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">测绘师</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
05、条件渲染
1、v-if:template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--v-if控制一个DOM标签-->
<h1 v-if="awesome">Vue is awesome!</h1>
<!--v-if通过template包含多个标签控制-->
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
<!--v-if和v-else-->
<div v-if="Math.random() > 0.5">Now you see me</div>
<div v-else>Now you don't</div><br/>
<!--v-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>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
awesome: true,
ok: true,
type: 'B'
}
})
</script>
</body>
</html>
2、v-if:key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--未管理可重复key之前,两个输入框的值仅需输入一次,且一直都是相同的-->
<!-- <template v-if="loginType === 'username'">-->
<!-- <label>Username</label>-->
<!-- <input placeholder="Enter your username"/>-->
<!-- </template>-->
<!-- <template v-else>-->
<!-- <label>Email</label>-->
<!-- <input placeholder="Enter your email address"/>-->
<!-- </template><br/>-->
<!-- <button v-on:click="convert()"/>-->
<!--管理可重复key之后,两个输入框需要分别输入,输入的值是不同的-->
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template><br/>
<button v-on:click="convert()"/>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
loginType: 'username',
num: true
},
methods: {
convert: function (){
this.num = !this.num
if (this.num === true){
this.loginType = 'username'
}else {
this.loginType = 'hhhh'
}
}
}
})
</script>
</body>
</html>
3、v-show
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
</div>
<!--v-show也是用于根据条件展示元素的选项,其用法和v-if大致一样
不同于v-if的是:v-show的元素始终会被渲染并保留在DOM只能。v-show知识简单地切换元素的CSS property display-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
06、列表渲染
1、v-for数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul id="app">
<!--v-bind:key可以复用-->
<li v-for="item in items" v-bind:key="item.message">
{{item.message}}
</li>
<!--在v-for中,还可以支持第二个参数,即当前的索引,of的效果和in的效果一样-->
<li v-for="(item, index) of items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
parentMessage: 'Parent',
}
})
</script>
</body>
</html>
2、v-for对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul id="app" class="demo">
<!--遍历对象里面的元素-->
<li v-for="value in object">
{{ value }}
</li>
<hr/>
<!--遍历对象时可以输出第二参数:键名-->
<li v-for="(value, name) in object">
{{name}}:{{ value }}
</li>
<hr/>
<!--遍历对象时可以输出第三参数:索引-->
<li v-for="(value, name, index) in object">
{{index}}:{{name}}:{{ value }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
</script>
</body>
</html>
3、维护状态
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul id="app">
<!--在v-for中,还可以支持第二个参数,即当前的索引,of的效果和in的效果一样-->
<!--为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,
你需要为每项提供一个唯一 key attribute:-->
<li v-for="(item, index) of items" v-bind:key="item.id">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
parentMessage: 'Parent',
}
})
</script>
</body>
</html>
4、数组更新检测-变更方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
Vue将被侦听的数据的变更方法进行了包裹,他们也将会触发视图更新
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
我们可以打开控制台,然后对前面的例子的items数组尝试调佣更新方法,比如
app.items.push({message: 'Zar'})表示标识为app对象的items数组属性添加数据message
-->
<div id="app">
<li v-for="item in items" v-bind:key="item.id">
{{item.message}}
</li>
<button @click='del'>删除数组元素pop</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
parentMessage: 'Parent',
},
methods: {
del: function () {
this.items.pop();
},
}
})
</script>
</body>
</html>
4、数组更新检测-替换数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
变更方法顾名思义,会变更调用了这些方法的原始数组。相比之下,
也有非变更方法,例如,filter()、contact()、slice()。
他们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,
可以用型数组替换旧数组
-->
<div id="app">
<li v-for="item in items" v-bind:key="item.id">
{{item.message}}
</li>
<button @click='change'>替换数组filter获取匹配oo的元素</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
parentMessage: 'Parent',
},
methods: {
change: function () {
this.items = this.items.filter(function (item) {
return item.message.match(/oo/)
})
},
}
})
</script>
</body>
</html>
5、显示过滤或排序后的结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
有时候,我们想要显示一个数组经过过滤或者排序后的版本,而不实际变更或重置元素数组。
在这种情况下,可以创建一个计算属性来返回过滤或排序后的数组
-->
<div id="app">
<!--使用计算属性的方法过滤数组-->
<li v-for="n in evenNumbers">
{{ n }}
</li>
<hr/>
<!--计算属性不适用得到情况下(嵌套for循环)-->
<ul v-for="set in sets">
<li v-for="m in even(set)">
{{m}}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
numbers: [ 1, 2, 3, 4, 5 ],
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
})
</script>
</body>
</html>
6、v-for里使用值范围
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。-->
<div id="app" class="demo">
<span v-for="n in 10" :key="n">{{ n }} </span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
7、template上使用v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<template v-for="item in items">
<li>{{ item.message }}</li>
</template>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue",
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
}
})
</script>
</body>
</html>
8、v-for与v-if一同使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--先判断是否不为空-->
<ul v-if="items.length">
<!--遍历数组-->
<li v-for="todo in items">
{{ todo.message }}
</li>
</ul>
<!--如果数组为空-->
<p v-else>No todos left!</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue",
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
}
})
</script>
</body>
</html>
9、组件上使用v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<my-component v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id">
</my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component("my-component",{
props: {
item: '',
index: '',
},
template: "<li>{{index}}--{{item.message}}</li>"
})
let vm = new Vue({
el: "#app",
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Coo' },
{ message: 'Xoo' },
],
}
})
</script>
</body>
</html>
07、事件处理
1、监听事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
可以用v-on指令监听DOM事件,并在触发时运行一些JavaScript代码
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的,一般是通过绑定事件名称
-->
<div id="app">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
counter: 0
}
})
</script>
</body>
</html>
2、事件处理方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
name: "Jack"
},
methods: {
greet: function (event){
// `this` 在方法里指向当前 Vue 实例
alert("Hello"+this.name+"!")
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
</script>
</body>
</html>
3、内联处理器中的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--除了直接绑定一个方法,也可以在内联JavaScript语句中传入参数并调用方法-->
<div id="app">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
},
methods: {
say: function (message) {
alert(message)
}
}
})
</script>
</body>
</html>
3、内联处理器中访问原生DOM事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--除了直接绑定一个方法,也可以在内联JavaScript语句中传入参数并调用方法-->
<div id="app">
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
},
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
alert(this)
}
alert(message)
}
}
})
</script>
</body>
</html>
4、事件修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。
尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
-->
<div id="app">
<!--阻止单击事件继续传播-->
<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>
<!--2.1.4 新增-->
<!--点击事件将只会触发一次-->
<a v-on:click.once="doThis"></a>
<!--2.3.0 新增-->
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
5、按键修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
在监听键盘事件时,我们经常需要检查 详细的按键是哪个。VUe允许Wiev-on在监听键盘事件时添加按键修饰符:
-->
<div id="app">
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
2.1.0 新增:可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl
.alt
.shift
.meta
-->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
},
methods: {
submit: function (){
alert(this)
}
}
})
</script>
</body>
</html>
6、系统修饰键-exact修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
.exact修饰符允许你控制由精确的系统修饰符组合触发得到事件
-->
<div id="app">
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">即使 Alt 或 Shift 被一同按下时也会触发</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">有且只有 Ctrl 被按下的时候才触发</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">没有任何系统修饰符被按下的时候才触发</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
},
methods: {
onClick: function () {
alert(this)
},
onCtrlClick: function () {
alert(this)
}
}
})
</script>
</body>
</html>
6、系统修饰键-鼠标按钮修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
2.2.0 新增
.left
.right
.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
-->
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
7、为什么在THML中监听事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
为什么在HTML中监听事件
你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。
但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,
它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:
1.扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
2.因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
3.当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。
-->
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
08、表单输入绑定
1、基本用法-文本框input
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input v-model="message" placeholder="请输入">
<p>Message is: {{ message }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: ""
}
})
</script>
</body>
</html>
2、基本用法-多行文本testarea
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{message}}</p>
<br/>
<textarea v-model="message" placeholder="请输入内容"></textarea>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: ""
}
})
</script>
</body>
</html>
3、基本用法-复选框CheckBox
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--单个复选框,绑定到布尔值:-->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label><br/>
<!--多个复选框,绑定到同一个数组:-->
<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>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue",
checked: '',
checkedNames: []
}
})
</script>
</body>
</html>
4、基本用法-单选框radio
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="radio" id="one" value="One" v-model="picked">
<input type="radio" id="two" value="two" v-model="picked">
<input type="radio" id="three" value="three" v-model="picked">
<input type="radio" id="four" value="four" v-model="picked">
<br/>
<span>你的选项是:{{picked}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue",
picked: ''
}
})
</script>
</body>
</html>
5、基本用法-选择框selected
可以用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 作为事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--单选时,绑定一个数据源-->
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
</select><br/>
<span>你的选择是:{{selected}}</span>
<hr/>
<!--多选时,绑定一个数组数据源multiple-->
<select v-model="selectedNums" multiple>
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
</select><br/>
<span>你的选择是:{{selectedNums}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
selected: "",
selectedNums: []
}
})
</script>
</body>
</html>
对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
6、值绑定-单选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">{{picked}}
<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">{{toggle}}
<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>{{selected}}
<hr/>
<input type="radio" v-model="pick" v-bind:value="a">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
picked: '',
pick: "",
selected: '',
toggle: '',
a: ''
}
})
</script>
</body>
</html>
7、值绑定-复选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input
id="test"
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
<span>{{toggle}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
toggle: ""
}
})
</script>
</body>
</html>
8、值绑定-选择框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<select v-model="selected">
<!-- 内联对象字面量 -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
selected: ""
}
})
</script>
</body>
</html>
9、修饰符-lazy修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。
你可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步:-->
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">{{msg}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: ""
}
})
</script>
</body>
</html>
10、修饰符-number修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--如果想自动将用户的输入值转为数值类型,
可以给 v-model 添加 number 修饰符:-->
<input v-model.number="age" type="number">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
age: ""
}
})
</script>
</body>
</html>
11、修饰符-trim修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--如果要自动过滤用户输入的首尾空白字符,
可以给 v-model 添加 trim 修饰符:-->
<input v-model.trim="msg">{{msg}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: ""
}
})
</script>
</body>
</html>
12、用在组件上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--HTML 原生的输入元素类型并不总能满足需求。幸好,
Vue 的组件系统允许你创建具有完全自定义行为且可复用的输入组件。
这些输入组件甚至可以和 v-model 一起使用!-->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
09、组件基础
1-基本示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--注意当点击按钮时,每个组件都会各自独立维护它的 count。
因为你每用一次组件,就会有一个它的新实例被创建-->
<!--因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,
例如 data、computed、watch、methods 以及生命周期钩子等。
仅有的例外是像 el 这样根实例特有的选项。-->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
2-data必须是一个函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
/*在这里我们发现组件虽然是vue实例的复用,但是组件的data是一个函数,
而不像vue实例提供一个对象,之所以一个组件的data选项必须是一个函数,
是因为每个实例可以维护一份被返回对象的独立拷贝,如果不是函数的话,
那么一个组件的数据发生变化,其他复用的数据也会随其发生同步变化*/
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
v3-组件的组织
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>通常一个应用会以一棵嵌套的组件树的形式来组织:</div>
<div>例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。</div>
<div>为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。全局注册的组件可以在应用中的任何组件的模板中使用。</div>
</body>
</html>
4-通过Prop向子组件传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
<hr/>
<!--自定义组件渲染数组-->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('blog-post', {
data: function () {
return {
}
},
props: ['title'],
template: `<h4>{{ title }}</h4>` })
let vm = new Vue({
el: "#app",
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
</script>
</body>
</html>
5-单个根元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component('blog-post', {
data: {},
props: ['post'],
/*如果我们发布的博客有标题,正文,时间,评论等等组件嵌套而成
* 所以我们需要定义一个嵌套式的组件,由于每一个组件都只能有
* 一个根元素,所以我们需要在一个根元素div下定义嵌套的模板
*/
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
let vm = new Vue({
el: "#app",
data: {
posts: [
{
title: '学习vue',
content: '从官网学习vue'
},
{
title: '学习vue',
content: '从官网学习vue'
}
]
}
})
</script>
</body>
</html>
6-监听子组件事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<!-- :post="post"代表组件的post属性等值为post的值-->
<!--父组件监听一个事件enlarge-text,子组件
通过调用内建的 $emit 方法并传入事件名称来触发一个事件:-->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
:post="post"
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component('blog-post', {
props: ['post'],
/*嵌套组件,监听子组件的事件*/
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">Enlarge text</button>
<div v-html="post.content"></div>
</div>
`
})
let vm = new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [
{
title: '学习vue',
content: '从官网学习vue'
},
{
title: '学习vue',
content: '从官网学习vue'
}
],
postFontSize: 1
}
})
</script>
</body>
</html>
7-使用事件抛出一个值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
有的时候用一个事件来抛出一个特定的值是非常有用的。
例如我们可能想让 <blog-post> 组件决定它的文本要放大多少。
这时可以使用 $emit 的第二个参数来提供这个值:
-->
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<!--通过 $event 访问到被抛出的这个值-->
<blog-post
v-for="post in posts"
v-bind:key="post.id"
:post="post"
v-on:enlarge-text="postFontSize += $event"
></blog-post>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component('blog-post', {
props: ['post'],
/*v-on:click="$emit('enlarge-text', 0.5)"中的0.5与父组件监听的$event对应*/
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text', 0.5)">Enlarge text</button>
<div v-html="post.content"></div>
</div>
`
})
let vm = new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [
{
title: '学习vue',
content: '从官网学习vue'
},
{
title: '学习vue',
content: '从官网学习vue'
}
],
postFontSize: 1
}
})
</script>
</body>
</html>
8-在组件上使用v-model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
使用方法总结
首先我们看第12行标签,,通过v-model绑定vue实例数据源的searchText属性,
这样就等价于将数据源的数据绑定到组件custom-input的value属性上面,从而实现数据双向绑定-->
<div id="app">
<custom-input v-model="searchText"></custom-input>
{{searchText}}
<!--上面的表达式等价于下面这一条-->
<custom-input v-bind:value="searchText"></custom-input>
{{searchText}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
Vue.component('custom-input', {
props: ['value'],
/*:value这个value是props属性里面的*/
template: " <input v-bind:value=\"value\" v-on:input=\"$emit('input', $event.target.value)\">"
})
let vm = new Vue({
el: "#app",
data: {
searchText: ''
},
methods: {
}
})
</script>
</body>
</html>
9-通过槽分发内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
和HTML元素一样,我么经常需要向一个组件传递内容,比如下面
-->
<div id="app">
<alert-box>
<span>Something bad happened.</span><br/>
</alert-box>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong><br/>
<slot></slot>
<slot></slot>
</div>
`})
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
10-动态插件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--动态插件的意思:不同组件之间进行动态切换,比如点击不同分类
如何实现动态组件:通过在<component>中添加一个特殊元素is attribute来实现-->
<div id="app">
<button-counter></button-counter>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
let vm = new Vue({
el: "#app",
data: {
message: "hello vue"
}
})
</script>
</body>
</html>
11-解析DOM模板时的注意事项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,
对于哪些元素可以出现在其内部是有严格限制的。而有些元素,
诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。
-->
<table>
<blog-post-row></blog-post-row>
</table>
<!--这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,
并导致最终渲染结果出错。幸好这个特殊的 is attribute 给了我们一个变通的办法:-->
<table>
<tr is="blog-post-row"></tr>
</table>
</body>
</html>