Vue
第1节 安装与部署
- 直接
<script>
引入 - 使用命令行工具CLI快速搭建脚手架
- CDN的方式:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- npm:
npm install vue
第2节 创建第一个vue应用
- vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统
- vue.js可分为视图和脚本两个部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{ message }} <!--左右双大括号声明一个变量-->
</div>
<script type="text/javascript">
var app = new Vue({ //通过new Vue的方式获取一个Vue的应用,会返回一个对象,称为应用对象
//在new Vue的时候需要传递一个对象作为参数,该对象有两个重要的属性:el(元素)和data
el: '#app', //用id选择器选择标签
data: { //data用于保存数据,在视图中声明的变量需要在data中赋值
message: 'Hello Vue!'
}
});
</script>
</body>
</html>
第3节 数据与方法
- 当一个Vue实例被创建时,它将data对象中的所有的属性加入到Vue的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
- 如果想要一个变量能够为响应式,需要在new Vue之前进行声明
- 方法:Object.freeze(),会阻止修改现有的属性,即相应系统无法再追踪变化
- 除了数据属性,Vue实例还暴露了一些有用的实例属性与方法,他们都有前缀$,以便与用户定义的属性区分开来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{ a }}
</div>
<script type="text/javascript">
var data = { a : 1 };
var vm = new Vue({ //一般用vm变量存放Vue对象
el: '#app',
data: data
});
vm.a = "111";
data.a = "123"; //上下两句的作用是一样的
//Object.freeze(data); //这之后data的变化不会再更新
vm.$watch('a', function (newValue, oldValue) {
console.log(newValue,oldValue);
})
vm.$data.a = "222"; //输出222 111
</script>
</body>
</html>
第4节 生命周期
-
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
-
生命周期钩子需要以属性的形式声明在new Vue的时候传递的对象内,这个属性是一个函数,在vue应用运行的每个阶段会自动调用已声明的生命周期函数
-
注意,生命周期函数不能使用箭头函数(箭头函数中没有this
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div id="app"> {{ msg }} </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: "hi vue" }, //在实例初始化之后,数据观测(data observer)和event/watcher 事件配置之前被调用 //即整个页面创建之前调用的生命周期 beforeCreate:function(){ console.log('beforeCreate'); }, //在实例创建完成后被立即调用 //在这一步,实例已经完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event事件回调 //然而,挂载阶段还没开始,$el属性目前不可见 created:function(){ console.log('created'); }, //在挂载开始之前被调用:相关的渲染函数首次被调用 beforeMount:function(){ console.log('beforeMount'); }, //el被新创建的vm.$el替换,挂载成功 mounted:function(){ console.log('mounted'); }, //数据更新时调用 //数据变化之前被调用的函数 beforeUpdate:function(){ console.log('beforeUpdate'); }, //组件DOM已经更新,组件更新完毕 updated:function(){ console.log('updated'); } }); setTimeout(function(){ //3s之后将msg文本更新 vm.msg = "change..."; },3000) </script> </body> </html>
-
actived方法:keep-alive组件激活时调用,该钩子在服务器渲染期间不被调用。
-
deactived方法:keep-alive组件停用时调用,该钩子在服务器渲染期间不被调用。
-
beforeDsetory方法:实例/页面销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器渲染期间不被调用。
-
dsetory方法:实例/页面销毁后调用。Vue实例指示的所有东西都会解绑定,所有的时间监听器会被移除,所有的子实例也会被销毁。该钩子在服务器渲染期间不被调用。
-
errorCaptured方法:当捕获一个来自子孙组件的错误时被调用。
-
第5,6节 模板语法
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
Vue从一定层面上提高了js的执行效率
插值
文本
- 数据绑定最常见的形式就是使用“Mustache”语法 (左右双大括号的方式包含一个变量) 的文本插值
<div id="app">
{{ msg }}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: "hi vue"
},
});
</script>
-
通过v-once指令,可以执行一次性地插值,当数据改变时,插值处的内容不会更新
<div id="app" v-once> {{ msg }} </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: "hi vue" }, }); vm.msg = "hi.."; //msg的值不会被改变 </script>
原始HTML
- 双大括号会将数据解释为普通文本,而不是HTML代码。为了输出真正的HTML,需要使用v-html指令
<div id="app">
<p>Using mustaches: {{ rawHtml }}</p>
<p v-html="rawHtml"></p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
rawHtml:'<span style="color:red">this is should be red</span>'
},
});
</script>
特性
-
使用vue为html标签绑定属性,使用v-bind指令:
v-bind:属性="属性值"
test...<div id="app"> <div v-bind:class="color">test...</div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { color:'red' // color:'blue' }, }); </script> <style type="text/css"> .red{color:red;} .blue{color:blue; font-size:100px;} </style>
使用JavaScript表达式
- vue模板完全支持JavaScript的表达式,直接运用双大括号即可
<div id="app">
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<!--将字符串拆分成字符,返回一个字符数组,反序,再结合成字符串-->
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
number: 10,
ok: true,
message: 'vue'
},
});
</script>
指令
- 指令是带有
v-
前缀的特殊特性,指令特性的预期值是单个JavaScript表达式(v-for
是特殊情况) - 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM
<div id="app">
<p v-if="seen">现在你看到我啦~</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
seen: true,
// seen: false
},
});
</script>
参数
一些指令能够接收一个“参数”,在指令的名称之后以冒号表示
v-bind
指令可以用于响应式地更新HTML特性
<div id="app">
<a v-bind:href="url">...</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
url: "https://learning.dcloud.io/#/?vid=6"
},
});
</script>
- 这里href是参数,告知v-bind指令将该元素的href特性与表达式url的值绑定
修饰符
指令的修饰符是以半角句号.
指明的特殊后缀,用于支出一个指令应该以特殊的方式绑定
<div id="app">
<div @click="click1">
<div @click.stop="click2"> <!--当前的click事件执行完毕后就会停下来-->
click me
</div>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
methods:{
click1:function(){
console.log('click1...');
},
click2:function(){
console.log("click2...")
}
}
});
</script>
第7节 class与style绑定
绑定动态样式
- 可以传给
v-bind:class
一个对象,以动态切换class:
<div id="app">
<div
v-bind:class="{ active : isActive}"
style="width: 200px; width: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActive: true,
// isActive: false
}
});
</script>
<style type="text/css">
.active{background:#FF0000}
</style>
- 可以在对象中传入更多属性来动态切换多个class。v-bind:class指令也可以与普通的class属性共存
<div id="app">
<div
class="static"
v-bind:class="{ active : isActive , green : isGreen }"
style="width: 200px; width: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActive: true,
isGreen: true
}
});
</script>
<style type="text/css">
.test{font-size:30px}
.green{color:#00FF00}
.active{background:#FF0000}
</style>
-
v-bind:class可以以数组的形式绑定多个样式,绑定动态样式时采用三元运算符的形式
<div id="app"> <div class="static" v-bind:class="[ 'active' , isGreen ? 'green' : '' ]" style="width: 200px; width: 200px; text-align: center; line-height: 200px;"> hi vue </div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { isActive: true, isGreen: true } }); </script> <style type="text/css"> .test{font-size:30px} .green{color:#00FF00} .active{background:#FF0000} </style>
绑定内联样式
- 使用v-style进行内联样式的动态绑定
<div id="app">
<div
:style="{color:color , fontSize:size}">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
color: '#FF0000',
size: '50px'
}
});
</script>
-
可以使用三元运算符的形式
<div id="app"> <div :style="{color:color , fontSize:size , background: isRed ? '#FF0000' : ''}"> hi vue </div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { color: '#FFFFFF', size: '50px' } }); </script>
第8节 条件渲染
v-if
指令用于条件渲染这一块内容。这块内容只会在指令的表达式返回truthy值的时候被渲染v-else-if
即为ifelse语法
<div id="app">
<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 type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
type: ""
}
});
</script>
v-show
用于根据条件展示元素- v-show的元素始终会被渲染并保留在DOM中,只是简单地切换元素的css属性display
- 当变量为false时,在控制台中打开HTML页面,有
<h1>
标签,只是会设置display=none
<div id="app">
<h1 v-show="ok">Hello!</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
ok : true
}
});
</script>
- v-if vs v-show
- v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;它也是惰性的,若初始渲染时条件为假,则什么也不做直至条件第一次变为真,才会开始渲染条件快
- v-show不管初始条件是什么都,元素总是会被渲染,通过css进行切换
- v-if有更高的切换开销,v-show有更高的初始渲染开销。如果需要频换切换,使用v-show好,如果在运行时条件很少改变,用v-if好
第9节 列表渲染
- 使用
v-for
遍历数组对象。v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。
<div id="app">
<ul>
<li v-for="item in items">
{{ item.message }}
</li>
<li v-for="item,index in items"> //得到索引和变量
{{ index }}{{ item.message }}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
items:[
{message: 'Foo'},
{message: 'Bar'}
]
}
});
</script>
-
使用v-for遍历对象的属性
- {{ value }}
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> <li v-for="value,key in object"> //获取对象属性的值和名称 {{ key }} : {{ value }} </li> </ul> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { object: { title: 'title', author: 'author', publishedAt: '2000-00-00' } } }); </script>
-
当 Vue 正在更新使用
v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
-
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key
属性:<li v-for="item,index in items" v-bind-key="index"> {{ index }}{{ item.message }} </li> <li v-for="value,key in object" :key="key"> //:key为缩写形式 {{ key }} : {{ value }} </li>v
第10节 事件绑定
- 使用
v-on
指令监听DOM事件,并在触发时运行一些JavaScript代码
<div id="app">
<div id="example-1">
<button v-on:click="counter += 1">数值:{{ counter }}</button>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
counter: 0
}
});
</script>
- 实际开发中,事件处理逻辑比较复杂,所以不能直接把JavaScript代码写在v-on指令中。因此,v-on可以接收一个需要调用的方法名称
<div id="app">
<div id="example-1">
<button v-on:click="greet('abc')">Greet</button> //js方法中可传递参数
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
name : "vue"
},
methods:{
greet : function(str) {
alert(str),
alert(this.name) //方法内可以调用vue内的data数据
}
}
});
</script>
-
在内联语句处理器中访问原始的DOM事件,可以采用特殊变量
$event
把它传入方法<div id="app"> <button v-on:click="warn('Form cannot be submitted yet.', $event)"> Submit </button> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', methods: { warn: function (message, event) { // 现在我们可以访问原生事件对象 if (event) event.preventDefault() alert(message) } }); </script>
事件修饰符
- 常见的事件修饰符有:
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件继续传播 -->
<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>
第11节 表单输入绑定
基础用法
- 可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。 v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:- text 和 textarea 元素使用
value
属性和input
事件; - checkbox 和 radio 使用
checked
属性和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
- text 和 textarea 元素使用
<div id="app">
<div id="example-1">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<br />
<textarea v-model="message2" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line">{{ message2 }}</p>
<br />
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">checked: {{ 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>Picked: {{checkedNames}}</span>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: "",
message2: "",
checked: "",
checkedNames: []
}
});
</script>
-
使用双向绑定之后,通过对data属性值的设置来完成对表单的默认值进行操作
var vm = new Vue({ el: '#app', data: { //设置表单的默认值 message: "test", message2: "hi", checked: "tow", checkedNames: ['Jack','Jhon'] }, methods:{ submit:function(){ //声明一个对象类型的变量,将所有表单的值收集起来 var postObj = { msg1: this.message, //获取各个表单的提交信息 msg2: this.message2, chexkval: this.checkedNames }; console.log(postObj); } } });
第12节 组件基础
-
组件是可复用的vue实例,在开发中,经常将重复使用的实例进行封装
-
vue使用Vue.component函数,第一个参数是组件名称(短横线或驼峰法命名),第二个参数以对象的形式去描述一个组件
-
因为组件是可复用的vue实例,所以他们与new vue接收相同的选项
-
这些组件是全局注册的,在注册之后可以用在任何新创建的vue根实例的模板中
<div id="app"> <button-counter title="title1:"></button-counter> <button-counter title="title2:"></button-counter> //每个组件的数据时封闭在组件内部的,相互并没有影响 </div> <script type="text/javascript"> Vue.component('button-counter', { props:['title'], //为组件定义属性,可在模板内对其进行应用和渲染 data: function() { return { count : 0 } }, template:'<div><h1>hi...</h1><button v-on:click="count++">{{ title }}You clicked me {{ count }} times.</button></div>', //在组件内显示多个标签 }) var vm = new Vue({ el: '#app', data: { }, }); </script>
-
组件的事件监听
<div id="app">
<button-counter title="title1:" @clicknow="clicknow">
<h2>hi...h2</h2> //在组件中插入HTML文本
</button-counter> //通过事件绑定去接收emit函数所触发的事件
</div>
<script type="text/javascript">
Vue.component('button-counter', {
props:['title'],
data: function() {
return {
count : 0
}
},
template:'<div><h1>hi...</h1><button v-on:click="clickfun">{{ title }}You clicked me {{ count }} times.</button><slot></slot></div>' ,
//通过<slot>标签声明一个组件的插槽,通过插槽可以声明任意的一个html标签
methods:{
clickfun: function () {
this.count++;
this.$emit('clicknow',this.count);
//通过此方法去触发一个事件,第一个参数是事件名,第二个参数是可携带的参数
}
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods:{
clicknow : function(e){
console.log(e);
}
}
});
</script>
第13节 组件注册
- 局部注册:全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
- 在new vue中的component属性内注册
```html
<div id="app">
<test></test>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
},
components:{
test:{
template:"<h2>h2...</h2>"
}
}
});
</script>
```
-
在模块系统中局部注册
注意局部注册的组件在其子组件中不可用
var ComponentA = { /* ... */ } var ComponentB = { components: { 'component-a': ComponentA }, // ... }
import ComponentA from './ComponentA.vue' export default { components: { ComponentA }, // ... }
在对象中放一个类似
ComponentA
的变量名其实是ComponentA: ComponentA
的缩写,即这个变量名同时是:- 用在模板中的自定义元素的名称
- 包含了这个组件选项的变量名
第14节 单文件组件
- 使用Vue.component定义全局组件的缺点:
- 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
- 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
\
- 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
- 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript, 而不能使用预处理器,如 Pug (formerly Jade) 和 Babel
- 安装npm,vue-cli,webpack
npm install -g @vue/cli
npm install -g webpack
-
- 选择创建文件的目录
vue ui
:启动vue的图形化处理界面- 新建一个项目,包管理器选择npm
- 目录结构:
- public:打包之后用于部署到生产环境下的目录
- src:用于开发的目录
- components:整个项目的组件目录
- HelloWorld.vue:单文件组件
- App.vue:项目的入口文件,完成对组件的引入工作
- components:整个项目的组件目录
- 自定义组件:
- components内新建vue
<template>html标签</template>
<script>export default{name,props{name:{type,default}},methods,data(){}}</script>
<style>css样式</style>
- 在app.vue内对组件进行引入
- 通过import语法引入自定义组件
- 在components内进行局部注册
- 在模板中使用组件标签# vue
- components内新建vue
第1节 安装与部署
- 直接
<script>
引入 - 使用命令行工具CLI快速搭建脚手架
- CDN的方式:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- npm:
npm install vue
第2节 创建第一个vue应用
- vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统
- vue.js可分为视图和脚本两个部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{ message }} <!--左右双大括号声明一个变量-->
</div>
<script type="text/javascript">
var app = new Vue({ //通过new Vue的方式获取一个Vue的应用,会返回一个对象,称为应用对象
//在new Vue的时候需要传递一个对象作为参数,该对象有两个重要的属性:el(元素)和data
el: '#app', //用id选择器选择标签
data: { //data用于保存数据,在视图中声明的变量需要在data中赋值
message: 'Hello Vue!'
}
});
</script>
</body>
</html>
第3节 数据与方法
- 当一个Vue实例被创建时,它将data对象中的所有的属性加入到Vue的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
- 如果想要一个变量能够为响应式,需要在new Vue之前进行声明
- 方法:Object.freeze(),会阻止修改现有的属性,即相应系统无法再追踪变化
- 除了数据属性,Vue实例还暴露了一些有用的实例属性与方法,他们都有前缀$,以便与用户定义的属性区分开来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{ a }}
</div>
<script type="text/javascript">
var data = { a : 1 };
var vm = new Vue({ //一般用vm变量存放Vue对象
el: '#app',
data: data
});
vm.a = "111";
data.a = "123"; //上下两句的作用是一样的
//Object.freeze(data); //这之后data的变化不会再更新
vm.$watch('a', function (newValue, oldValue) {
console.log(newValue,oldValue);
})
vm.$data.a = "222"; //输出222 111
</script>
</body>
</html>
第4节 生命周期
-
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
-
生命周期钩子需要以属性的形式声明在new Vue的时候传递的对象内,这个属性是一个函数,在vue应用运行的每个阶段会自动调用已声明的生命周期函数
-
注意,生命周期函数不能使用箭头函数(箭头函数中没有this
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div id="app"> {{ msg }} </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: "hi vue" }, //在实例初始化之后,数据观测(data observer)和event/watcher 事件配置之前被调用 //即整个页面创建之前调用的生命周期 beforeCreate:function(){ console.log('beforeCreate'); }, //在实例创建完成后被立即调用 //在这一步,实例已经完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event事件回调 //然而,挂载阶段还没开始,$el属性目前不可见 created:function(){ console.log('created'); }, //在挂载开始之前被调用:相关的渲染函数首次被调用 beforeMount:function(){ console.log('beforeMount'); }, //el被新创建的vm.$el替换,挂载成功 mounted:function(){ console.log('mounted'); }, //数据更新时调用 //数据变化之前被调用的函数 beforeUpdate:function(){ console.log('beforeUpdate'); }, //组件DOM已经更新,组件更新完毕 updated:function(){ console.log('updated'); } }); setTimeout(function(){ //3s之后将msg文本更新 vm.msg = "change..."; },3000) </script> </body> </html>
-
actived方法:keep-alive组件激活时调用,该钩子在服务器渲染期间不被调用。
-
deactived方法:keep-alive组件停用时调用,该钩子在服务器渲染期间不被调用。
-
beforeDsetory方法:实例/页面销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器渲染期间不被调用。
-
dsetory方法:实例/页面销毁后调用。Vue实例指示的所有东西都会解绑定,所有的时间监听器会被移除,所有的子实例也会被销毁。该钩子在服务器渲染期间不被调用。
-
errorCaptured方法:当捕获一个来自子孙组件的错误时被调用。
-
第5,6节 模板语法
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
Vue从一定层面上提高了js的执行效率
插值
文本
- 数据绑定最常见的形式就是使用“Mustache”语法 (左右双大括号的方式包含一个变量) 的文本插值
<div id="app">
{{ msg }}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
msg: "hi vue"
},
});
</script>
-
通过v-once指令,可以执行一次性地插值,当数据改变时,插值处的内容不会更新
<div id="app" v-once> {{ msg }} </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: "hi vue" }, }); vm.msg = "hi.."; //msg的值不会被改变 </script>
原始HTML
- 双大括号会将数据解释为普通文本,而不是HTML代码。为了输出真正的HTML,需要使用v-html指令
<div id="app">
<p>Using mustaches: {{ rawHtml }}</p>
<p v-html="rawHtml"></p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
rawHtml:'<span style="color:red">this is should be red</span>'
},
});
</script>
特性
-
使用vue为html标签绑定属性,使用v-bind指令:
v-bind:属性="属性值"
test...<div id="app"> <div v-bind:class="color">test...</div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { color:'red' // color:'blue' }, }); </script> <style type="text/css"> .red{color:red;} .blue{color:blue; font-size:100px;} </style>
使用JavaScript表达式
- vue模板完全支持JavaScript的表达式,直接运用双大括号即可
<div id="app">
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<!--将字符串拆分成字符,返回一个字符数组,反序,再结合成字符串-->
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
number: 10,
ok: true,
message: 'vue'
},
});
</script>
指令
- 指令是带有
v-
前缀的特殊特性,指令特性的预期值是单个JavaScript表达式(v-for
是特殊情况) - 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM
<div id="app">
<p v-if="seen">现在你看到我啦~</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
seen: true,
// seen: false
},
});
</script>
参数
一些指令能够接收一个“参数”,在指令的名称之后以冒号表示
v-bind
指令可以用于响应式地更新HTML特性
<div id="app">
<a v-bind:href="url">...</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
url: "https://learning.dcloud.io/#/?vid=6"
},
});
</script>
- 这里href是参数,告知v-bind指令将该元素的href特性与表达式url的值绑定
修饰符
指令的修饰符是以半角句号.
指明的特殊后缀,用于支出一个指令应该以特殊的方式绑定
<div id="app">
<div @click="click1">
<div @click.stop="click2"> <!--当前的click事件执行完毕后就会停下来-->
click me
</div>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
methods:{
click1:function(){
console.log('click1...');
},
click2:function(){
console.log("click2...")
}
}
});
</script>
第7节 class与style绑定
绑定动态样式
- 可以传给
v-bind:class
一个对象,以动态切换class:
<div id="app">
<div
v-bind:class="{ active : isActive}"
style="width: 200px; width: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActive: true,
// isActive: false
}
});
</script>
<style type="text/css">
.active{background:#FF0000}
</style>
- 可以在对象中传入更多属性来动态切换多个class。v-bind:class指令也可以与普通的class属性共存
<div id="app">
<div
class="static"
v-bind:class="{ active : isActive , green : isGreen }"
style="width: 200px; width: 200px; text-align: center; line-height: 200px;">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActive: true,
isGreen: true
}
});
</script>
<style type="text/css">
.test{font-size:30px}
.green{color:#00FF00}
.active{background:#FF0000}
</style>
-
v-bind:class可以以数组的形式绑定多个样式,绑定动态样式时采用三元运算符的形式
<div id="app"> <div class="static" v-bind:class="[ 'active' , isGreen ? 'green' : '' ]" style="width: 200px; width: 200px; text-align: center; line-height: 200px;"> hi vue </div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { isActive: true, isGreen: true } }); </script> <style type="text/css"> .test{font-size:30px} .green{color:#00FF00} .active{background:#FF0000} </style>
绑定内联样式
- 使用v-style进行内联样式的动态绑定
<div id="app">
<div
:style="{color:color , fontSize:size}">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
color: '#FF0000',
size: '50px'
}
});
</script>
-
可以使用三元运算符的形式
<div id="app"> <div :style="{color:color , fontSize:size , background: isRed ? '#FF0000' : ''}"> hi vue </div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { color: '#FFFFFF', size: '50px' } }); </script>
第8节 条件渲染
v-if
指令用于条件渲染这一块内容。这块内容只会在指令的表达式返回truthy值的时候被渲染v-else-if
即为ifelse语法
<div id="app">
<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 type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
type: ""
}
});
</script>
v-show
用于根据条件展示元素- v-show的元素始终会被渲染并保留在DOM中,只是简单地切换元素的css属性display
- 当变量为false时,在控制台中打开HTML页面,有
<h1>
标签,只是会设置display=none
<div id="app">
<h1 v-show="ok">Hello!</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
ok : true
}
});
</script>
- v-if vs v-show
- v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;它也是惰性的,若初始渲染时条件为假,则什么也不做直至条件第一次变为真,才会开始渲染条件快
- v-show不管初始条件是什么都,元素总是会被渲染,通过css进行切换
- v-if有更高的切换开销,v-show有更高的初始渲染开销。如果需要频换切换,使用v-show好,如果在运行时条件很少改变,用v-if好
第9节 列表渲染
- 使用
v-for
遍历数组对象。v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。
<div id="app">
<ul>
<li v-for="item in items">
{{ item.message }}
</li>
<li v-for="item,index in items"> //得到索引和变量
{{ index }}{{ item.message }}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
items:[
{message: 'Foo'},
{message: 'Bar'}
]
}
});
</script>
-
使用v-for遍历对象的属性
- {{ value }}
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> <li v-for="value,key in object"> //获取对象属性的值和名称 {{ key }} : {{ value }} </li> </ul> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { object: { title: 'title', author: 'author', publishedAt: '2000-00-00' } } }); </script>
-
当 Vue 正在更新使用
v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
-
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key
属性:<li v-for="item,index in items" v-bind-key="index"> {{ index }}{{ item.message }} </li> <li v-for="value,key in object" :key="key"> //:key为缩写形式 {{ key }} : {{ value }} </li>v
第10节 事件绑定
- 使用
v-on
指令监听DOM事件,并在触发时运行一些JavaScript代码
<div id="app">
<div id="example-1">
<button v-on:click="counter += 1">数值:{{ counter }}</button>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
counter: 0
}
});
</script>
- 实际开发中,事件处理逻辑比较复杂,所以不能直接把JavaScript代码写在v-on指令中。因此,v-on可以接收一个需要调用的方法名称
<div id="app">
<div id="example-1">
<button v-on:click="greet('abc')">Greet</button> //js方法中可传递参数
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
name : "vue"
},
methods:{
greet : function(str) {
alert(str),
alert(this.name) //方法内可以调用vue内的data数据
}
}
});
</script>
-
在内联语句处理器中访问原始的DOM事件,可以采用特殊变量
$event
把它传入方法<div id="app"> <button v-on:click="warn('Form cannot be submitted yet.', $event)"> Submit </button> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', methods: { warn: function (message, event) { // 现在我们可以访问原生事件对象 if (event) event.preventDefault() alert(message) } }); </script>
事件修饰符
- 常见的事件修饰符有:
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件继续传播 -->
<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>
第11节 表单输入绑定
基础用法
- 可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。 v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:- text 和 textarea 元素使用
value
属性和input
事件; - checkbox 和 radio 使用
checked
属性和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
- text 和 textarea 元素使用
<div id="app">
<div id="example-1">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<br />
<textarea v-model="message2" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line">{{ message2 }}</p>
<br />
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">checked: {{ 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>Picked: {{checkedNames}}</span>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: "",
message2: "",
checked: "",
checkedNames: []
}
});
</script>
-
使用双向绑定之后,通过对data属性值的设置来完成对表单的默认值进行操作
var vm = new Vue({ el: '#app', data: { //设置表单的默认值 message: "test", message2: "hi", checked: "tow", checkedNames: ['Jack','Jhon'] }, methods:{ submit:function(){ //声明一个对象类型的变量,将所有表单的值收集起来 var postObj = { msg1: this.message, //获取各个表单的提交信息 msg2: this.message2, chexkval: this.checkedNames }; console.log(postObj); } } });
第12节 组件基础
-
组件是可复用的vue实例,在开发中,经常将重复使用的实例进行封装
-
vue使用Vue.component函数,第一个参数是组件名称(短横线或驼峰法命名),第二个参数以对象的形式去描述一个组件
-
因为组件是可复用的vue实例,所以他们与new vue接收相同的选项
-
这些组件是全局注册的,在注册之后可以用在任何新创建的vue根实例的模板中
<div id="app"> <button-counter title="title1:"></button-counter> <button-counter title="title2:"></button-counter> //每个组件的数据时封闭在组件内部的,相互并没有影响 </div> <script type="text/javascript"> Vue.component('button-counter', { props:['title'], //为组件定义属性,可在模板内对其进行应用和渲染 data: function() { return { count : 0 } }, template:'<div><h1>hi...</h1><button v-on:click="count++">{{ title }}You clicked me {{ count }} times.</button></div>', //在组件内显示多个标签 }) var vm = new Vue({ el: '#app', data: { }, }); </script>
-
组件的事件监听
<div id="app">
<button-counter title="title1:" @clicknow="clicknow">
<h2>hi...h2</h2> //在组件中插入HTML文本
</button-counter> //通过事件绑定去接收emit函数所触发的事件
</div>
<script type="text/javascript">
Vue.component('button-counter', {
props:['title'],
data: function() {
return {
count : 0
}
},
template:'<div><h1>hi...</h1><button v-on:click="clickfun">{{ title }}You clicked me {{ count }} times.</button><slot></slot></div>' ,
//通过<slot>标签声明一个组件的插槽,通过插槽可以声明任意的一个html标签
methods:{
clickfun: function () {
this.count++;
this.$emit('clicknow',this.count);
//通过此方法去触发一个事件,第一个参数是事件名,第二个参数是可携带的参数
}
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods:{
clicknow : function(e){
console.log(e);
}
}
});
</script>
第13节 组件注册
- 局部注册:全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
- 在new vue中的component属性内注册
```html
<div id="app">
<test></test>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
},
components:{
test:{
template:"<h2>h2...</h2>"
}
}
});
</script>
```
-
在模块系统中局部注册
注意局部注册的组件在其子组件中不可用
var ComponentA = { /* ... */ } var ComponentB = { components: { 'component-a': ComponentA }, // ... }
import ComponentA from './ComponentA.vue' export default { components: { ComponentA }, // ... }
在对象中放一个类似
ComponentA
的变量名其实是ComponentA: ComponentA
的缩写,即这个变量名同时是:- 用在模板中的自定义元素的名称
- 包含了这个组件选项的变量名
第14节 单文件组件
- 使用Vue.component定义全局组件的缺点:
- 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
- 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
\
- 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
- 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript, 而不能使用预处理器,如 Pug (formerly Jade) 和 Babel
- 安装npm,vue-cli,webpack
npm install -g @vue/cli
npm install -g webpack
-
- 选择创建文件的目录
vue ui
:启动vue的图形化处理界面- 新建一个项目,包管理器选择npm
- 目录结构:
- public:打包之后用于部署到生产环境下的目录
- src:用于开发的目录
- components:整个项目的组件目录
- HelloWorld.vue:单文件组件
- App.vue:项目的入口文件,完成对组件的引入工作
- components:整个项目的组件目录
- 自定义组件:
- components内新建vue
<template>html标签</template>
<script>export default{name,props{name:{type,default}},methods,data(){}}</script>
<style>css样式</style>
- 在app.vue内对组件进行引入
- 通过import语法引入自定义组件
- 在components内进行局部注册
- 在模板中使用组件标签
- components内新建vue