Vue简介
About 12 min
Vue简介
vue是什么
一套用于构建用户界面的渐进式JS框架
构建用户界面:数据--->界面
渐进式:Vue可以自底向上逐层的应用
简单应用:只需要一个轻量小巧的核心库
复杂应用:可以引入各式各样的Vue插件
vue的特点
- 采用组件化模式,提高代码复用率,让代码更好维护
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率

VUE-01
初识Vue
<!--安装VUE:当你使用script进行VUE安装之后,上下文中就注册了一个全局变量:Vue-->
<script src="../js/vue.js"></script>
<script>
/*
第一步:创建Vue实例
1. 为什么要new Vue(),直接调用不行吗
不行,因为直接调用Vue函数,不创建实例的话,会报错
Vue is a constructor and should be called with the `new` keyword
2. 关于Vue构造函数的参数:options
Vue框架要求这个options参数必须是一个纯粹的JS对象:{}
在{}对象中可以编写大量的key:value对
一个key:value就是一个配置项
主要是通过options这个参数来给Vue实例指定多个配置项
3. 关于template配置项
template配置项用来指定模板语句,模板语句是一个字符串形式的
什么是模板语句?
Vue框架自己制定了一些具有特殊含义的特殊符号
Vue的模板语句是Vue框架自己搞的一套语法规则
模板语句可以是一个纯粹的HTML代码,也可以是Vue中的特殊规则,也可以是HTML代码 + Vue的特殊规则
template后面的模板语句会被Vue框架的编译器进行编译,转换成浏览器能够识别的HTML代码
*/
const myVue = new Vue({
template: '<h1>Hello Vue</h1> '
})
/*
第二步:将Vue实例挂载到id='app'的元素位置
1. Vue实例都有一个%mount()方法,这个方法的作用是什么?
将Vue实例挂载到指定位置
2. #app显然是ID选择器
*/
myVue.$mount('#app')
</script>
关于template
<script>
/*
模板语句的数据来源:
1.谁可以给模板语句提供数据支持?data选项
2.data选项的类型是什么?Object|FUNCTION (对象或者函数)
3.data配置项的专业叫法:Vue实例的数据对象。data实际上是给整个Vue实例提供数据来源
4.如果data是对象的话,对象必须是纯粹的对象(含有零个或多个的key/value对)
5.data数据如何插入到模板语句当中?
{{}}这是Vue自己搞的一套语法,别的框架看不懂,浏览器也看不懂
Vue框架自己能看懂,这种语法在Vue框架中被称为:模板语法中的插值语法
怎么用?
{{data的key}}
*/
new Vue({
template : '<h1>Hello Vue,名字是{{name}},{{age}}</h1>',
data : {
name : '123',
age : '17'
}
}).$mount('#app')
</script>
关于data
data是Vue实例的数据对象,给模板语句提供数据支持
data的写法
data : { name : '123', age : '17' }
data的value除了字符串,数字,还可以是对象,数组等
关于el
el配置项指定了这个Vue实例挂载的元素是谁
<script>
/*
* 一个Vue实例可以接管多个容器吗?
* 1.不可以,一个Vue只能接管一个容器,一旦接管到容器后,即使后面有相同的容器,Vue也不管
*
* */
new Vue({
el : '.app2',
data : {
name : 'zhangsan'
}
})
//这个Vue实例想接管.app2容器,但是已经被接管了。所以他只能光棍
new Vue({
el : '.app2',
data : {
name : 'lisi'
}
})
</script>
template配置项深入
<div id="app">
<div><h1>{{msg}}</h1> </div>
</div>
<script>
//Vue.config是Vue的全局配置对象
//productionTip可以设置是否生成生产提示信息
Vue.config.productionTip = false;
//但是有时候不生效
//不生效可以直接去vue.js中修改
/*
* 关于template配置项:
* 1.template后面指定的是模板语句,但是模板语句中只能有一个根节点,比如<h1></h1><h1></h1>是错误的
* 2.只要data中的数据发生变化,模板语句一定会重新编译
* 3.如果使用template配置项的话,指定挂载位置的元素会被替换
* 4.好消息:可以不使用template编写模板语句,可以直接写到html标签中。Vue框架能够找到并且编译,然后渲染
*
* 关于$mount('#app):
* 也可以不使用$mount('#app)进行挂载了,在Vue配置项中有一个el
* el配置项可以和$mount('#app)达到同样效果
* 告诉vue实例接管哪个容器
* */
new Vue({
//错误的,template : '<h1>111</h1><h1>222</h1>'
//template: '<div><h1>{{msg}}</h1> </div>',
data : {
msg : 'Hello!!!'
},
el : '#app'
})
//}).$mount('#app')
</script>
VUE-02核心技术
模板语法之插值语法
<body>
<!--
{{里面可以写什么?}}
1.在data中声明的变量,函数等
2.常量
3.合法的js表达式
4.模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如Math和Date等
-->
<div id="app">
<!-- 变量、函数 -->
<h1>{{msg}}</h1>
{{sayHello()}}
{{sayHello}}
<h1>{{sayHello()}}</h1>
<!-- 常量 -->
<h1>{{100}}</h1>
<h1>{{'123'}}</h1>
<!-- 合法的js表达式 -->
<h1>{{1+1}}</h1>
<h1>{{'hello' + '1'}}</h1>
<h1>{{msg + 1}}</h1>
<h1>{{'msg' + 1}}</h1>
<h1>{{msg.split('').reverse().join('')}}</h1>
<!-- 错误的,不是表达式,这是语句-->
<!-- <h1>{{var a = 1}}</h1>-->
<!-- 在白名单里面的-->
<h1>{{Date}}</h1>
<h1>{{Math}}</h1>
<h1>{{Date.now()}}</h1>
</div>
<script>
new Vue({
data : {
msg : 'Hello!!!',//把msg看成变量
sayHello : function () {
console.log("qwq")
}
},
el : '#app'
})
</script>
</body>
模板语法之指令语法
<body>
<!--
指令语法:
1.什么是指令?有什么作用?
指令的职责是:当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM
2.Vue框架的所有指令的名字都以“v-”开始
3.插值是写在标签体中的,那么指令写在哪里呢?
Vue框架中,所有指令都写在HTML标签的属性里面,例如:
<span 写在这里> </span>,虽然指令写在属性位置上,但是这个指令浏览器是无法直接
看懂得,需要先让Vue框架进行编译,编译之后的内容浏览器是可识别的
4.指令的完整语法格式:
<HTML标签 v-指令名 : 参数="js表达式"></HTML标签>
表达式:之前在插值语法中{{这里可以写什么}},那么指令中的表达式就可以写什么
但是注意,表达式不要再加括号{{}}
不是所有的指令都有参数和表达式:
有的指令,不需要参数,也不需要表达式,例如 v-once
有的指令,不需要参数,但是需要表达式,例如 v-if=""
有的指令,既需要参数,又需要表达式,例如:v-bind:参数="表达式"
5.v-once指令
作用:只渲染元素一次,随后的重新渲染,元素及其所有的子节点将被视为静态内容并跳过,这可以用于优化更新性能
6.v-if="表达式"指令
作用:表达式的执行结果是一个bool类型,true/false
true就将v-if所在标签渲染到浏览器
-->
<div id="app">
<h1>{{msg}}</h1>
<h1 v-once>{{msg}}</h1>
</div>
<script>
new Vue({
data : {
msg : 'Hello!!!',//把msg看成变量
sayHello : function () {
console.log("qwq")
}
},
el : '#app'
})
</script>
</body>
v-bind详解
<body>
<!--
v-bind指令详解:
1.这个指令的作用:
2.语法格式:
<标签 v-bind:参数="表达式"></标签>
3.编译原理
编译前:<标签 v-bind:参数="表达式"></标签>
编译后:<标签 参数="表达式"></标签>
注意:
第一:编译时,参数名变为属性名
第二:表达式会关联data,data发生改变,表达式执行结果就发生改变
4.v-bind因为使用频繁有简写方式:
只是针对v-bind提供了<img :src="imgsrc">
5.什么时候使用插值语法,什么时候使用指令?
凡是标签体中的内容想要动态,使用插值语法
只要想让HTML标签属性动态,使用指令语法
-->
<div id="app">
<!-- msg是变量名,参数名理论上可以随便写,但是实际需要有意义-->
<h1 v-bind:x="msg"></h1>
<img src="crop1583675488643.jpg">
<img v-bind:src="imgsrc">
<img :src="imgsrc">
<!-- 这样写可以吗?不行,在属性内部使用插值语法已经移除了-->
<!-- <a href="{{url}}"></a>-->
</div>
<script>
new Vue({
el : '#app',
data : {
msg : 'Hello 123',
imgsrc : 'crop1583675488643.jpg'
}
})
</script>
</body>
v-model
注意关于v-model的简写,因为是双向,它的属性一定是value,所以v-model:value="" 可以简写v-model=""
<body>
<!--
v-bind和v-model的区别和联系:
1.v-bind和v-model这两个指令都可以完成数据绑定
2.v-bind是单向数据绑定 data>视图
3.v-model是双向数据绑定 data<>视图
4.v-bind可以使在任何标签,v-model只能用在表单类元素:input,textarea,select
5.v-model简写方式
v-model:value="表达式" 简写为 v-model="表达式"
v-bind:value="表达式" 简写为 :参数="表达式 "
-->
<div id="app">
v-bind:<input type="text" v-bind:value="name1"><br>
v-model:<input type="text" v-model:value="name2">
</div>
<script>
new Vue({
el : '#app',
data : {
name1 : 'zh',
name2 : 'ww'
}
})
</script>
</body>
初识MVVM模式
MVVM是什么?
M:Model 模型
V:View 视图
VM:ViewModel 视图模型,它是MVVM的核心部分
MVVM是目前前端开发领域中流行的开发思想—一种架构模式
目前前端的大部分主流框架都实现了这个MVVM思想,例如Vue、React

VUE虽然没有完全遵循MVVM模型,但是Vue的设计也受到了它的启发
Vue框架也基本是符合MVVM思想的
MVVM模型倡导Model和View进行分离,为什么要分离Model和View?
- 假如Model和View不分离,使用原生的JS代码写项目:
- 如果数据发生改动,接下来需要编写大片的操作DOM的元素的 JS 代码
- 将Model和View分离后,出现VM核心,这个VM把脏活累活做完了
- 也就是说,Model发生改变,VM自动更新View,当View发生变化,VM自动更新Model。
- 我们不再需要编写操作DOM的JS代码
在Vue中,View就是HTML标签,Model就是data配置项,VM就是Vue实例
认识Vue实例
<!--
1.通过Vue实例可以访问哪些属性?
Vue实例中的属性很多,有的以$开始,有的以_开始
所有以$开始的属性,可以看成是公开的属性,供程序员使用
所有以_开始的属性,可以看成是私有的属性,是Vue框架底层使用的
通过VM也可以访问Vue实例对象的原型对象上的属性,如vm.$delete
-->
<div id="app">
<h1></h1>
</div>
<script>
let dataobj = {
msg : 'HelloVue'
}
const vm = new Vue({
el : '#app',
data : {
msg : dataobj
}
})
//按理说msg是dataobj的属性
console.log('dataobj' + dataobj.msg)
//为什么可以通过vm去访问msg?
//因为Vue底层使用了数据代理机制
//要搞明白数据代理机制,需要先明白Object.defineProperty()
console.log('vm' + vm.msg)
</script>
Object.defineProperty()
<!--
Object.defineProperty()
1.这个方法是ES5新增的
2.方法的作用:给对象新增属性,或者设置对象原有的属性,
3.怎么用?
Object.defineProperty(给哪个对象新增属性, '新增的属性叫什么', {给新增的属性配置key:value对})
4.第三个参数是属性相关的配置项,有哪些配置项?有什么用?
value(这里的value是配置项
):给属性指定值
writable:true/false,true可修改
getter方法:不需要手动调用,当读取属性值时自动调用
getter方法必须有返回值,这个返回值就是这个属性它的值
setter方法:不需要手动调用,当修改属性值时自动调用
setter方法上有一个参数,这个参数可以接受传过来的值
注意,当配置项中有set和get时,不能有value和writable配置项
-->
<script>
let phone = {}
let temp//用中间变量解决递归的
//给phone对象新增一个color属性
Object.defineProperty(phone, 'color', {
//value:'绿',
//writable:true,
get : function () {
console.log('getter')
//return this.color,这样做会产生递归
return temp
},
set : function (val) {
console.log('setter',val)
temp = val
}
})
</script>
数据代理机制
<!--
1.什么是数据代理机制?
通过访问代理对象的属性,来间接访问目标对象的属性
数据代理机制的实现依赖于Object.defineProperty()方法
2.ES6新特性:
在对象中的函数 :function可以省略
-->
<div id="app"></div>
<script>
const vm = new Vue({
el : '#app',
data : {
msg : 'noodle'
},
//msg : 'noodle111'
})
console.log(vm.msg)
</script>
<script>
//目标对象
let target = {
name : 'zhangsan'
}
//代理对象
let proxy = {}
//要实现数据代理机制的话,就需要给proxy加一个name属性。
//注意:代理对象新增的这个属性的名字和目标对象的属性名要一样
Object.defineProperty(proxy, 'name', {
/*get : function () {
return target.name
},
set : function (val) {
target.name = val
}*/
get() {
return target.name
},
set(val) {
target.name = val
}
})
/*
let target = {
name : '123'
}
const vm = new Vue({
el : '#app',
data : target
})
*/
</script>
数据代理对属性名的要求
<!--
1.为什么Vue不给以_和$开始的属性名做数据代理
如果允许给_或者$开始的属性名做数据代理的话,VM这个Vue实例上可能会出现属性名冲突
2.Vue中,data对象的属性名不能以_和$开始
3.$开头是给开发者准备的一些可用变量, _开头是关于Vue内部实现细节
4.如果在data 中定义 _xxx 变量,它会被存储在 this.$data._xxx,不会挂载到实例的 _xxx 属性上
-->
<div id="app">
<h1>{{msg}}</h1>
</div>
<script>
const vm = new Vue({
el : '#app',
data : {
msg : 'Hello Vue',
_name : 'zhangsan',
$age :10
},
_name2:'lisi'
})
</script>
VUE-03

vue2的组件结构
<script>
data() {
},
methods: {
},
//计算属性
compueted: {
outputContent() {
console.log('computed执行了')
return 'xxxxx'
}
},
//侦听器
watch: {
title(newVal, oldVal){
//xxxxxxx
}
}
</script>
组件通信
- 父传子
<template>
<!--在父组件调用-->
<HelloWorld
msg=""
count=10
></HelloWorld>
<!--也可以这样调用-->
<HelloWorld
msg=""
:count="count"
></HelloWorld>
</template>
<script>
export default {
name: 'Hello',
props: {
msg: String,
count: {
type: [String, Number],
defalut: 100,
// required: true
}
}
}
</script>
- 子传父
自定义事件
<template>
<!--在父组件调用-->
<HelloWorld
msg=""
count=10
@xxxxx="handler"
></HelloWorld>
</template>
<script>
methods: {
xxxxx
}
</script>
子组件调用$emit('xxxxxxx'
)触发
<script>
methods: {
handler() {
// xxxxxx
this.$emit('xxxxxxx')
}
}
</script>
插槽
定义插槽:
<slot ></slot>
具名插槽:
<slot name="xxx"></slot>
父组件使用:
<template v-slot:footer>xxxxx</template>
<template #footer>xxxxx</template>
子组件向父组件传递值
<template>
<slot name="footer" :child="childData" :other="otherData"></slot>
</template>
父组件接受
<!-- 父组件 -->
<ChildComponent>
<template #footer="slotProps">
<!-- slotProps 是一个对象,包含子组件传递的所有数据:{ child: ..., other: ... } -->
{{ slotProps.child }}
</template>
</ChildComponent>