Vue2使用
本文是根据 尚硅谷Vue2.0+Vue3.0全套教程 整理出的学习笔记。仅供自我参考。
Vue官网
引入Vue
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
阻止Vue在启动时生成生产提示
Vue.config.productionTip = false
安装Vue浏览器插件
点击"Vue插件安装引导页面"可以按照你所使用的浏览器选择你对应的插件
初识Vue
- 想让Vue工作就必须创建一个Vue实例,且要传入一个配置对象。
- root容器里的代码依然符合html规范,只不过混入的一些特殊的Vue语法
- root容器里的代码被称为Vue模板
- Vue实例和容器是一一对应的
- 真实开发中会有一个Vue实例,并且会配合着组件一起使用
- {{xxx}}中的xxx要写js表达式且xxx可以自动读取到data中的所有属性
- 一旦data中的数发生改变,那么模板(页面)中用到该数据的地方也会自动更新。
准备容器
准备一个容器
<div id="root">
<h1>hello,{{name}}</h1>//注意:双花括号里面也可以放js表达式
</div>
创建Vue实例
<script type="text/javascript">
new Vue({
el:"root",//el用于指定当前Vue容器为哪个容器服务,值通常为css选择器字符串
data:{//用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
name:"zhagnchenzhou“
}
})
</script>
Vue模板语法
<a v-bind:href="name">点我点我</a>
Vue模板语法有两大类
- 插值语法:
- 功能:用于解析标签体内容
- 写法:{{xxx}}xxx是js表达式,且可以直接读取到data中的所有属性
- 指令语法
- 功能:用于解析标签(包括标签属性,标签体内容,绑定事件。。。。)
- 举例: v-bind:href="xxx",或简写为 :href="xxx" xxx同样要写js表达式,且可以读取到data中的所有属性。
- 备注:Vue中有很多指令,且形式都是v-???.
v-bind
单向数据绑定,数据只能从data流向页面。
<input type="text" v-bend:value="name">
<input type="text" :value="name">//简写
v-model
双向数据绑定,数据不仅能从data流向页面,还能从页面流向data。
<input type="text" v-model:value="name">
<input type="text" v-model="name">//简写
注意:
双向绑定(v-model)只能应用在表单类元素上,如(input select)等v-model:value可以简写为v-model,因为v-model默认收集的就是value值``
Vue中el与data的两种写法
el的两种写法
el写法1:直接写进Vue实例中
new Vue(
el:"#root"
)
el写法2:不用写进Vue实例中,后面调用$mount方法。
vue.$mount("#root")
Vue实例中所有以$开头的都是给程序员用的。以_开头的都是Vue底层在用的
data的两种写法
data写法1:直接写进Vue实例中
new Vue({
data:{
}
})
data写法2:函数式形式
new Vue({
data:function(){
//注意此处不能写成箭头函数,否则this变成了window
return{
name:"xxx"
}
}
})
注意以后学到组件时,data必须使用函数式写法
MVVM模型
- M:对应的是data中的数据
- V:对应的是模板
- VM:视图模型(ViewModel)对应的是Vue实例对象
data中写的数据最终都拆散被挂载到Vue对象上了双花括号模板中能看到所有Vue中装载的东西
数据代理
拖过对象代理,操作一个对象修改另 一个对象中的属性就叫数据代理。
给一个对象添加(或定义)属性
Object.defineproperty
let persion={
name:"张三",
sex:"男“,//这样写的属性是可枚举的
//age:18
}
//这样写的属性是不可枚举的
Object.defineproperty(persion,"age",{
value:18,
enumerable:true//控制属性是否可以枚举,默认值false
writeabel:true//控制属性是否可以被修改,默认值是false
configurable:true//控制属性是否可以被删除,默认值false
get:function(){//有了这个方法后,每次访问age就会调用此方法。从而返回age的值
return "hello"
}
get(){//上面的简写
return "hello"
}
set(value){//当有人修改age属性时,set函数就会被调用,且会受到修改的具体值。
console.log("有人修改了age属性,且值是",value)
}
})
简单的数据代理
let obj = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,"x",
get(){
return obj.x
}
set(value){
obj.x=value
}
)
Vue中的数据代理
Vue中data里面的数据也是运用上面的方法把data中的数据由Vue代理。Vue通过调用Vue中set方法将data中的属性修改。通过调用Vue中get方法,拿到data中的属性值。
Vue中的事件处理
Vue中事件的方法虽然也可以写在data中,但是一般我们不这么做,因为放在data中Vue框架会为我们做一层数据劫持,而方法明显不需要做这些东西。否则会造成资源的浪费。
无参数
模板端没有指定参数时,js端带默认参数event
//模板
<button v-on:click="showInfo">点我显示提示信息</button>
//可以简写成下面代码
<button @click="showInfo">点我显示提示信息</button>
new Vue({
el:"#root",
data:{},
methods:{
showInfo(event){//不带参数默认是event
//console.log(event.target.innerText)
//console.log(this)//此处的this是vm (Vue实例对象)
alert("hello world ")
}
}
})
带自定义参数
//传值
<button @click="showInfo1(1111)">点我显示提示信息</button>
new Vue({
el:"#root",
data:{},
methods:{
showInfo1(number){//带参数,没有event了
alert(number)
}
}
})
带自定义参数加事件
//传值带event
<button @click="showInfo1(1111,$event)">点我显示提示信息</button>
new Vue({
el:"#root",
data:{},
methods:{
showInfo1(number,a){//带event参数
alert(number)
alert(a)
}
}
})
Vue事件修饰符
- 正常情况下我们使用如下方法会弹出alert,点击确定会跳转到相应的页面
<a href="www.baidu.com" @onclick="showInfo">点我提示信息</a>
methods:{
showInfo(e){
alert("你好")
}
}
- 增加事件修饰符,阻止跳转行为
<a href="www.baidu.com" @onclick="showInfo">点我提示信息</a>
methods:{
showInfo(e){
e.preventDefault()//此处阻止跳转行为
alert("你好")
}
}
- 在事件后增加修饰符阻止跳转
//此处增加.prevent修饰符
<a href="www.baidu.com" @onclick.prevent="showInfo">点我提示信息</a>
- Vue中其他事件修饰符
- 修饰符可以连着写
@click.prevent.stop//先阻止默认事件再停止冒泡
@click.stop.prevent//先停止冒泡再阻止默认事件
键盘事件
@keydown @keyup
- 按下回车调用showInfo方法
//.enter是按键别名
<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"/>
- 常用别名
- 其他编码 Enter的真正键值是13enter==13
@keyup="showInfo"
@keydown.13="showInfo"
console.log(e.target.value)//输出按键名字及值
- 自定义别名
Vue.config.keyCodes.自定义键名 = 键妈
- 只有摁下ctrl+y时才提示
@keyup.ctrl.y="showInfo"
计算属性
模板中的方法调用{{showInfo()}}每次在模板解析时都会被调用。 计算属性是拿着已有属性去加工计算得到的属性。data中放的是属性。computed放的是计算属性。vm._data没有计算属性。
computed:{//接收对象
fullName:{
//get 1.初次读取fullName时被调用。2.所依赖数据发生改变时被调用
get(){
//当有人读取fullName时,get就会被调用。且返回值就作为fullName的值
console.log("get被调用了")//此处this是Vue
return "abcd"
}
//set 如果fullName以后会需要修改,则写set
set(value){
console.log("set",value)
const arr = value.split("-")
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
计算属性有缓存,当第一次执行后就缓存下来,只要他所依赖的数据没改变他就不会再次被调用
2. 对比methods
methods只要模板解析就会被调用。没有缓存
methods:{
fullName(){
console.log("@---fullName")
return this.firstName + "-" + this.lastName
}
}
计算属性简写
大多数情况下计算属性是不需要set的,不需要get,那么确定计算属性只读不改我们就可以用简写方式。
//此处不接受对象了直接把fullName当成一get个函数用。
fullName:function(){
}
监视属性
- 监控当一个值改变了,执行某些特定操作
data:{
isHot:true,
}
watch:{
isHot:{
//handler当isHot放生改变时被调用
handler(){
console.log("isHot被修改了")
}
}
}
watch:{
isHot:{
//handler当isHot放生改变时被调用,参数,新值,旧值
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
}
}
- 一上来就通知,监控的值变化了immediate:true//初始化时让handler直接把名字拿出来调用一下
watch:{
isHot:{
immediate:true,
//handler当isHot放生改变时被调用,参数,新值,旧值
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
}
}
- 第二种监视方式,通过vm创建监视
vm.$watch("isHot",{
immediate:true,
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
})
- 深度监视
假如说a是data对象中对象的对象 data.numbers.a 此时不是深度监视
watch:{
'numbers.a':{ //只监视nunbers中的一个a的改变
immediate:true,
//handler当isHot放生改变时被调用,参数,新值,旧值
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
}
}
用deep:true监视多级结构中,所有属性的变化。
watch:{
numbers:{
deep:true,
handler(){
console.log("numbers改变了")
}
}
}
- 监视的简写形式 当不使用immediate和deep时可以使用简写形式。
watch{
isHot(newValue,oldValue){
consle.log("isHot被修改了",newValue,oldValue)
}
}
vm.$watch("isHot",function(newValue,oldValue){ consle.log("isHot被修改了",newValue,oldValue) } )
watch与compute区别
watch麻烦,计算属性简单。当两者都能实现时用计算属性。当面临其他复杂的情况,比如异步计算时, 用watch。
绑定样式
绑定样式适用于,样式类名不确定。需要动态指定 绑定样式示例: :class="mood"
<div class="basic" :class="mood" @click="changeMode">{{ name }}</div>
methods:{
changeMood(){
this.mood = "happy"
}
}
条件渲染
<h2 v-show="false">欢迎来到{{ name }}</h2>
<h2 v-if="false">欢迎来到{{ name }}</h2>
- template 配合v-if处理多个元素的隐现效果
遍历
- v-for 遍历数组
2. v-for 遍历对象
- v-for 遍历字符串
- v-for 遍历指定次数
- 总结
key的原理
- 向数组中前面添加元素存在效率问题
向数组中前面添加元素时,假如key要用index的话会造成原始虚拟dom的key和新虚拟dom的key所有元素都对不上。产生大量的对比失败从而导致后面的都重新生成原先已经处理生成过真实dom的元素。同时还有可能造成错位问题。非差异的东西会对比成功从而向上错位一个。 2. 错位问题
用index当key可能出现错位问题,此时需要用index
- key的工作原理
``
4. 虚拟dom的对比算法
拿一样key的进行对比:
对比里面的节点,不一样的,则计算新增,对比一样的直接复用。
- 遍历列表时Id作为key
- 总结
列表过滤
效果图
- 用watch实现
2. 用计算属性实现
当watch和计算属性都能实现的时候,优先使用计算属性,因为它比较简单
列表排序
-
效果图
-
具体代码
Vue检测数据改变的原理
- 修改马冬梅信息
- 代码(生效和不生效演示)
- 原理(数据劫持)
一个模拟的数据检测
_Vue.set()方法动态增加data中的属性
- 当时没有写一些属性,后面想补回来。直接写不行得用(Vue.set(target,key,val))。
或者
- Vue.set局限性 Vue.set只能给data里面的某一个对象追加属性,不可以给data追加属性。
Vue检测数组中元素的变化
通过检测数组中下面几个方法,来检测数组变化
Vue 运用包装技术把上面蓝色框中的方法进行包装,我们在Vue中调用的这几个方法已经不是原汁原味的js方法了
总结:
数据劫持和代理,都离不开你ObjectDefinePropoty方法。
收集表单数据
- 让点击文字也能获取表单
- 具体界面
- 具体实现代码
xml
vue
4. 总结
过滤器
- 其中竖线叫管道符
2. 过滤器可以传参,也可以加默认值
3. 多个过滤器可以串联(此处是局部过滤器)
- 全局过滤器(必须在new Vue之前就写好)
- 过滤器可以用在插值语法和v-bind中,v-model中不能使用
用在v-bind中
总结:
v-text指令
v-html指令
-
与v-text不同 比v-text支持文本里存的html结构解析。
-
安全性问题
v-cloak指令
利用v-cloak配合js,解决当网速过慢时,vuejs没有加载出来导致界面出现模板代码的情况。
v-cloak当Vue加载完成时生成的dom中会自动去除
总结:
v-once指令
v-once指令只渲染一次,后面vue就不再改变了。
v-pre指令
在没有插值语法的节点增加v-pre指令可跳过节点,加快程序编译速度。
vue自定义指令
- 函数式
函数式,相当于对象式的 第一步+第三步。
2. 对象式
对象式把vue绑定页面显示到界面过程划分为3步执行,可以完成更加细致的操作。
- 自定义全局指令(对象式)
2. 自定义全局指令(函数式)
总结:
注意:指令内的this是window
Vue生命周期
- 绑定样式重名时,用简写规则
简写成
- 生命周期定义
- debugger,js代码中打断点
- 声明周期图
总结:
Vue组件的理解
非单文件组件的使用
- 创建组件
2. 注册组件
局部注册
全局注册
- 使用组件
总结:
组件使用注意点
在配置项中指定组件在开发者工具中的名字
组件的嵌套
Vue Componete构造函数
Vue实例与组件实例
组件(VC)有的功能VM全有,但是VM可以通过el指定为哪个容器服务,VC没有。且组件中的data必须是函数形式(为了避免多个地方调用相同组件时,data重复)。
一个重要的内置关系
视频 059 没看懂
单文件组件
.vue文件就是组件,我们不可以在组件script脚本中创建Vue实例(new Vue)。
暴露方式
- 模板
2. 脚本
3. 样式
4. 脚本的导入
脚手架文件分析
Vue.config.js配置文件
ref 属性
ref属性类似于html中的id,但是当他用到组件中的时候和Id有些不同
- 介绍
2. ref的使用
props配置
向组件中传递数据信息。
- 传递数据
注意:此时age传过去的是字符串类型,要想改成Int类型,只需要写成 :age="18" 加冒号的意思是把引号中的东西当成表达式执行
- 接收和使用数据
- 接收时对要接收的数据类型进行限定
- 接收时对要接受的数据进行数据类型,默认值,require进行配置
注意: 不能多声明外面没有传进来的东西,传进来的东西是不允许改的。
- 修改的方式
data中定义新属性,新属性默认值设置为传过来的值,在方法中修改新属性值。
总结:
mixin混入
混入是值两个组件共享一个配置。
- 创建公共的js (mixin.js)
- 使用混合(先导入,后配置)
混合方法可以把公共的和自有的进行整合到一起全部应用。混合原则上两边都有的,以原有的为主(比如说data和methods的方法等,但是生命周期方法则都会执行)。不破坏组件原有的数据。
- 全局混合的导入和使用
总结:
Vue中的插件
Vue中插件的本质就是一个对象,对象中需要有install()方法
-
定义插件
-
导入和应用插件
- 应用插件时,带参数
在inistall方法总依次定义参数接一下就行。
、
总结:
scoped样式
默认情况下,不同插件中在标签中定义的样式都是被混合在一起的。假如两个插件中有同样的样式配置,则后面的会覆盖前面的。此时可给style标签增加scoped属性解决。
此时加上scoped的代码快样式只对当前插件生效
总结:
浏览器本地存储
组件自定义事件
通过父组件给子组件传递函数类型的props可以实现子给父传递数据(类似回调)
-
父组件定义回调事件,并传递给子组件:
-
子组件接收并调用:
给组件实例对象VC身上绑定事件
- 定义事件绑定:
- 定义事件:
3.子组件发射事件:
- 让事件只触发一次:
事件中传递多个值
- 传递多个值
传递
接收
- 传递对象
给组件自定义事件解绑
在子组件中解绑组件自定义事件
自定义事件注意点及总结
全局事件总线
- 事件总线需要符合下面条件
消息订阅与发布
$nextTick
介绍: nextTick所指定的回调函数会在dom节点更新完成之后再执行。比如点击按钮后文字编辑框并获得焦点。此时获得焦点需要在dom节点更新完成后执行。
动画效果
配置代理
协议名 主机名 端口号全都对上,才能是非跨域,浏览器访问不支持跨域。所以需要配置代理。跨域请求能正常发出,服务器也能正常相应,不过浏览器那边拿到后没有给开发者。
- 解决跨域 cors 。服务器跨域,带特殊响应头,需要后端人员处理
- jsonp,借助Script的src标签在引入外部资源的时候不受同源限制的特点解决跨域。需要前后端都处理。且只能解决get请求的跨域问题。
- 代理服务器解决跨域问题。
4.Vue Cli配置代理
默认插槽
- 模板中配置默认插槽
- 默认插槽的使用。
具名插槽
- 具名插槽的定义
- 具名插槽的使用
有时候我们在使用插槽时,不希望增加一层div布局结构,此时我们需要用template代替div包含内部结构,这一种情况下。Vue给我们提供了一种具名插槽使用的新写法。v-vlot:footer(插槽明)
- 作用域插槽,数据在子组件里面,但是数据的展示形式要在app里面,此时需要用到作用域插槽。
作用域插槽的定义。
作用域插槽的使用,此时要求必须template包含,且scope是组件中插槽传过来的数据对象。
插槽总结:
解构赋值
解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。
1、把数组中的值顺序赋值给不同变量
可以看出,变量赋值的顺序是和数组顺序一致的,从下标为0开始
let [a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
// 长度大于变量数量时,结果不会受到影响
let [a, b] = [10, 20, 30];
console.log(a); // 10
console.log(b); // 20
2、把对象中的属性同时赋值给与变量名相同的变量
方法与数组赋值很相似,仅仅是把数组变成了对象
注意:对象的顺序不会影响赋值的顺序,对象结构赋值对应的是相同的key属性
let { a, b } = { a: 10, b: 20 };
console.log(a); // 10
console.log(b); // 20
// 对象的顺序不会影响赋值的顺序,对象结构赋值对应的是相同的key属性
let { a, b } = { c: 10, b: 20, a: 30 };
console.log(a); // 30
console.log(b); // 20
3、变换变量
可以通过解构赋值实现变量的快速转变
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
4、忽略某些值
对于某些不需要的值,也可以跳过进行赋值
let [a, , b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 3
把数组前后分开赋值,后面变量赋值成数组
let [a, ...b] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // [2, 3, 4, 5]
VueX
在Vue中实现集中式状态管理的插件。
- 多组件间实现数据共享,全局总线实现。(多组建即读又写)。写起来有点乱。
- 多组件实现数据共享,Vuex实现
在Vue脚手架中,程序会先执行import语句,在执行当前文件中的代码。
Vuex原理图
Vuex开发环境搭建
基本使用
Vuex中getters配置项的准备和使用
mapStates
- 对象写法 导入
注意Js中{sum}这种写法会被转成{sum:sum},其中第二个sum代表一个变量,而不是字符串
- 数组写法
mapActions
Vuex模块化加命名空间
路由
路由的安装及相关理解
基本使用
- 路由组件和一般组件 由路由规则匹配出来,靠路由器渲染的组件叫路由组件。直接写在html中的组件叫一般组件。
路由组件一般放在pages文件夹中。
-
切换走的路由组件都是被系统销毁了。
-
路由组件身上都出现了两个新的东西.(route)
嵌套(多级)路由
路由的query参数
命名路由
路由的params参数
路由的props
解构赋值的连续写法
{query:{id,title}}
routerLink的replace属性
编程式路由
缓存路由组件
回退回去的组件数据切换回来,数据还让他存在。
两个新生命周期钩子
路由器缓存组件时,路由器中的timer一直执行,要想让其取消需要用到下面两个新的生命周期钩子进行处理。
前置路由守卫和后置路由守卫
前置路由守卫是路由切换前对系统做一定的校验,后置路由守卫是路由切换后做一些事情,比如说切换路由后改变浏览器页签显示的title等。
独享路由守卫
组件内路由守卫
路由的history模式与hash模式
#号后面的都是hash值,hash值最大的特点就是不会作为路径的一部分发给服务器,只是前端人员自己在玩。整个路由器一共有两种模式,默认开启hash工作模式,特点是里面有#,另一种就是history工作模式。