Vue2+3基础
第一个Vue程序
如何导入?
使用script进行Vue全局设置:
指定Vue实例挂载的位置
, Vue和js一样,都需要在script里写
第一步创建vue实例
1.为什么要new vue(),直接调用Vue不行吗?
不行,因为如果直接调用Vue()会报如下错误:
2.关于vue构造函数:options
options翻译为多个选项
Vue框架要求这个options参数必须是一个纯粹的js对象:{ }
在{ }对象中才能大量编写Key:value键值对
一个Key:value就是一个配置项,通过options参数给Vue实例指定多个配置项
3.关于template配置项:
template翻译为模板,用来指定模板语句,模板语句是一个字符串形式的:‘ ’
什么是模板语句?
Vue框架自己制定了一些具有特殊含义的特殊符号,有自己的语法规则,模板语句可以是一个纯粹的HTML代码,也可以是HTML+Vue,
template后边的模板语句会被Vue框架的编译器进行编译,转化为浏览器认识的HTML代码。
const myVue = new Vue({ template:'<h1>Hello! Vue!!</h1>' })
myVue.$mount('#app')
z在浏览器当中可以看到,没有div,只有模板语句,他是直接将id为app 的div替换成HTML语句的!
2.模板语句的数据来源
1.谁可以给模板语句提供数据支持呢?data选项
2.data选项的数据类型是什么?Object |Function(对象或者函数),也就是说,可以是数组。
3.data配置项专业叫法:Vue实例的数据对象(data实际上是整个Vue实例提供数据来源的)
4.如果data是对象,对象必须是纯粹的对象(含有0个或多个Key:value键值对)
5.data数据如何动态插入到模板语句中?
{{ }},这是Vue自己搞的一套语法,称为模板语法中的插值语法(胡子语法)
{{data的key}}
换行用 ` 或者+,注意:在{这里不能有字符包括空格{ }这里不能有字符包括空格}
3.template的配置项解释
1.template后边指定的是模板语句,但是模板语句只能有一个根节点,想多写加个div在div里边写
2.只要data中的数据发生变化,模板语句一定会重新编译。
3.可以不用template写模板语句,可以直接写在HTML里,这样挂载位置的元素也不会被替换。
关于¥mount(‘#app’)
在Vue中有一个el配置项
el的作用和¥mount()作用一样,都可以实现对Vue实例对象的挂载
el : '#app' == myvue.$mount('#app')
Vue的一夫一妻制
一个Vue实例只能接管一个容器,1对1
Vue核心技术(重点)
模板语法之插值语法{{}}
{{主要研究这里可以写什么?}}
1.在data中声明的变量、函数等都可以
2.常量都可以
3.只要是合法的JS表达式都可以
4.模板表达式都被放在沙盒中,如下能使用
模板语法之指令
指令语法:
1.什么是指令语法?有什么作用?
2.Vue框架中的所有指令都是v-开头
3.插值是写在标签体当中的,指令写在HTML的标签属性上。
4.指令语法规则:
指令的完整语法格式:
<Html标签 v-指令名:参数=“JS表达式”></Html标签>
注意指令表达式中不能再添加一个{{}}
不是所有的指令都需要参数和表达式
5.v-once 指令
作用:使用该指令后标签只渲染一次,所有子节点及元素都视为静态内容跳过,不会更新。
6.v-if="表达式"指令
作用:表达式的执行结果是一个布尔类型true/false,T成立,F不成立
7.v-bind指令
作用:用来使得某个属性的值成为动态效果
语法格式:v-bind参数="表达式" / :参数=“表达式”
来说说话bind像的model
v-bind和v-model都可以完成数据的动态绑定
v-bind是单项的数据绑定,可以用在任何标签上
v-model是双向的数据绑定,只能用在表单类元素上:input,select,textarea,这种和用户交互的标签上。
v-bind和v-model的简写方式:
bind v-bind:参数="表达式" 简写 :参数=“表达式”
model v-model:value="表达式" 简写 v-model=“表达式”
用v-model交互,bind不交互,以下是v-model,如果是bind,即使左边改变右边也不变
MVVM架构思想
将Model和View视图分离开,当View变化后,VM核心自动去更新Model,不需要自己写DOM的js代码。开发效率提高
认识VM
vue框架也收到MVVM思想启发,创建的Vue实例一般用vm命名
通过vm实例可以访问那些属性?
带$的是公开属性,一般程序员使用
带_的是私有属性,供Vue框架底层使用
通过vm也可以访问Vue实例对象原型对象上的属性:vm.$delete
为什么Vm可以获取到msg?
因为数据代理机制
数据代理机制基于object.defineProperty()
数据代理机制就是用一个临时对象去间接访问对象,达到直接访问的效果。
数据代理不会给$和_做代理,怕出错
data可以是对象,也可以是函数,学到组件就知道了
配置项enumerable,configurable
vue事件绑定,需要在Method里写回调函数才能调用
没加占位符
加了
this
method方法没有做数据代理,就是用变量代替
事件修饰符
@wheel是鼠标滚轮滑动
@keydown键盘按下不弹起发生
@keyup键盘按下并谈起发生
网站里边输入用户名密码回车自动获取id和ps就是用keyup事件所传的event对象的键值判断是否等于回车13自动登录的。
按键修饰符
常用的有修饰符,不常用的想用只能自定义了,或者直接在后边.key,就上边是说的根据获取的键值去判断是否是想要的目标值ASII
反转字符串
使用Vue原有属性经过一系列运算得到一个新的属性,叫做计算属性。
data对象当中的属性可以叫做Vue的原有属性。
语法格式
computed : {
计算属性1:{
set(val){}
get(val){}
}
}
简写就是
computed:{
计算属性(){
return ?
}
}
作用:代码复用,容易维护,效率高
计算属性简写格式和方法格式一样
watch监听
watch:{
}
属性简写
可以监视多个属性,用哪个监视哪个名字
immediate:true 立即执行
immediate: 其值是true或false,确认是否以当前的初始值执行handler的函数.
有一个固定的方法:handler(newValue,oldValue){}
如何获取new和old?
可以使用v-model指令双向绑定,用哪个就绑定哪个watch里的属性
this还是当前Vue实例。
如果该函数是箭头函数this就是window对象。
深度监视:当监视的属性里有很多属性要监视时,可以使用deep:true属性,就顶如(a.*)
handler:用来获取之前数据和现在改完数据
后期想添加监视怎么办?
和直接写有什么区别?
一个是一开始作为属性写到对象中,一个是后期通过调用api实现
当只调用handler属性时,可以直接简写,handler就像number的有参构造一样
后期监视简写
箭头函数()=>{}默认是找上级的this,但是不简写function()本身是window就不行
在Vue里加强了class和style
class绑定之字符串形式
v-bind不仅能绑定字符串,还可以绑定对象或者数组,所以.class样式可以与bind连用,实现动静结合
可以用true还是false选择用哪个JS样式
已经变成Vue的形状了,悲
条件渲染
关于v-if、v-else、v-else-if指令,就像后端的ifelse一样,成立立即执行。
v-show
也是页面上看不见,但是在F12后台可以看见代码,而v-if=false是不会看见代码,真正的隐形
v-show是修改了CSS样式的display数值达到的隐形,还是会加载,而v-if不会加载
template标签,起到一个占位符的作用,不会出现在页面上,也不会影响页面结构
v-for遍历
格式
可以实现动态列表
遍历对象属性
按照属性顺序读取
遍历字符串
按照拆分的字母和下标,s 0 、j 1
遍历指定的次数
和字符串差不多
按照数组元素和数组元素下标 1 0 、2 1
虚拟Dom机制和diff算法:
虚拟Dom是先将数据虚拟储存,当修改后会更新一个新的Dom与旧的用Diff算法去对比两个之间的差别,只有差别的地方才会重新部署,没有的不改变,提高执行效率
必须将key设置成主键,不然后边默认key是数组元素下标index,会导致列表错乱,
placeholder
filter过滤器
列表排序小技巧:可以鼠标单击触发修改data里的变量值,当赋值时,vm里会重新部署一遍,进而触发当type=1时的计算属性函数可以使用过滤器来完成
两个单选按钮在同一name下才能实现单选
model.类型转换number
删除前后空格
lazy延迟加载,等鼠标光标离开后才加载
这种指令不能在from表单上,会出现xss攻击,导致cookie泄露
v-clock
为了解决vue.js加载不出来导致页面vue代码不执行,页面显示源码的情况,出现了v-clock
解决方法,在头里加一个CSS样式,里边将display设置成none
[]代表所有标签
v-once
只在开始执行一次,后边直接成为静态内容
v-pre
不在vue编译,提高编译效率
自定义指令
函数式
对象式
响应式与数据劫持
什么叫做响应式,你写的数据能在页面上直接展示出来,或者更改一个数据,和这个数据有关的都叫做响应式。
数据劫持:其实就是set方法。
Vue生命周期
四个周期,八个钩子
从创建vm.$el后才有真实Dom
data改变就继续调用两个钩子,改变一次调用一次
这里的卸载销毁实际上是解绑Vue实例所有的监视器,自定义监听器,子组件等等。Vue实例还在
虽然beforeDestroy里监视器处于激活状态,但是不能用,内存中已经卸载了
组件
组件就是用来提高代码复用率的。
三部曲:创建组件、注册组件、使用组件
第一步创建组件,使用template实现模块化,在组件中,data必须是对象,且return返回一个对象
Vue当中可以使用自闭合标签的,但前提必须在脚手架环境中使用
全局注册
组件嵌套
注册的组件如果组件名和对象名一致可以简写
app : app
嵌套哪个组件就把组件名写到哪个组件下
Vm与Vc
vm包含vc,vc全称是VueComponent,Vue组件,是专门用来写组件的
vm和vc的原型对象是一个,所以能够互相访问,像共用一个父类,为了实现代码复用
重点:
导入导出
import,export,添加export以便其他文件能够导入他们
导出方式
单文件组件模型
导入
这里的X1是标签名,也就是说在template里边定义模板的X1标签名
脚手架
使用脚手架是为了浏览器能够认识.Vue文件,脚手架能够自动将VUe文件翻译成浏览器能够认识到Css,html,js代码
Vue配置项
render
实际上是被缩写成这样的
原代码
props配置项
当想更改属性值时,组件标签可以直接在标签内更改Value。像Html一样
有三种更改方式
props里还可以定义默认值default,添加必要性,必要性意思为不能为空
当想获取的值是数字或者其他值时,可以用V-bind标签,因为这个标签的返回值一定要是常量,对象。
props里的值不能修改,可以用个临时变量替代更改,展现数据也用那个临时变量
父组件中获取子组件
有什么用?可以用来修改子组件值,达到目的
给组件标签加上一个ref,顶如一个id。可以用this.$ref.属性值的方式获取到
不光组件,普通的Dom元素也可以定义id
因为不建议做Vue里使用Dom,所以这个ref实际上就是Dom里id的替代品
mixin混入:将组件间公共部分提取出来,不会和本身不会与同名的导入组件内函数冲突,就近原则
特殊的是,在8个钩子函数内,在同名的情况下,先执行mixin内的,再执行函数本身的
全局混入
混入是总结组件相同部分,实现代码复用
install方法里边形参可以是Vue对象和数据
scoped 关键字 局部样式
为了避免组件与组件之间样式名字相同造成代码替代。
在浏览器上实际在div上添加了一种编号,所以能区分开样式
自定义事件
通过代码的形状形式绑定事件
删除
回调函数的this
全局事件总线
消息的订阅与发布机制
pubsub-js
导入库
要使用箭头函数,要不没有this,因为本身没有this,使用箭头函数自动找外层的this也就是VC
记得摧毁前将函数解除
AJAX跨域问题
代理服务器跨域
代理服务器配置
简单代理
只能代理一个服务器
高级代理
pathRewrite:^/api替换成‘ ’空要不地址会带/api
Vuex
多个组件实现资源共享
vuex过程,表面上还是用的vue的data,method,进行一个简单的包装,核心内容交给vuex里的store.js去搞了,store有三个对象
action对象、mutations对象、store对象
action对象处理事件逻辑,如然后将数据传输到mutations里去更新数据也就是state对象,因为state是响应式处理,整个页面包括state里的数据就会更新。达到目的
dispath是分发
context指的是action的行为动作
业务逻辑简单可以跳过action,直接this.$store.commit
store对象和Vm里的data差不多
简单数字加一了解一下Vuex过程
//App.vue <template> <div> <h1>数字:{{$store.state.num}}</h1> <button @click="plusOne">点我加1</button> </div> </template> <script> export default { name : 'App', data() { return { startNum : 0 } }, methods: { plusOne(){ // 这里的代码在实际开发中可能会比较复杂。 // 业务逻辑复杂,代码比较多。 // 如果你将这些代码放到这里的话,这些业务逻辑代码无法得到复用。 // 无法在其他组件中使用,在其他组件中使用的时候,你还需要把这些代码再写一遍。 //this.$store.state.num++ // 调用vuex的API。 // dispatch是vuex的API。调用这个方法之后,store对象中的plusOne这个action回调函数会被自动调用。 // dispatch:分发 // 交给plusOne这个action去处理这个事儿。 this.$store.dispatch('plusOne', this.startNum) } }, } </script>
//Store.js // 引入Vue,因为下面使用Vuex插件的时候需要Vue import Vue from 'vue' // 引入vuex插件 import Vuex from 'vuex' // 使用插件 Vue.use(Vuex) // 创建三个vuex插件的核心对象:actions对象、mutations对象、state对象 const actions = { // N多个action // 每一个action都是一个callback(回调函数) // 在action这种回调函数中编写复杂的业务逻辑 // 有个原则:action是专门用来处理业务逻辑,或者说发送AJAX请求的。 //plusOne : function(){} // 简写 // context参数:context是vuex的上下文(context可以看做是store对象的缩小版) // value参数:传过来的数据 plusOne(context, value){ // 处理业务 value = value + 1 // 调用其它的action这个回调函数 //context.dispatch('otherAction', value) // 业务逻辑处理完成之后,继续向下一个环节走,就轮到了数据的更新。 // 提交上下文环境(所有的事儿都做完了,该最后一步了,更新数据了,怎么办?提交) context.commit('PLUS_ONE', value) }, // 这里可能还会有其它的action // ... /* otherAction(context, value){ console.log(6666) } */ } const mutations = { // N多个mutation // 每一个mutation都是一个callback(回调函数) // 每一个mutation这个回调函数的作用就是:更新state // 只要state一更新,因为是响应式的,所以页面就重新渲染了。 // state参数:状态对象 // value参数:上一环节传过来的数据 PLUS_ONE(state, value){ state.num += value } } // 等同于Vue当中的data(只不过这里我们不叫做数据,叫做状态) // 状态对象(数据对象),已经做了响应式处理的。 const state = { num : 0 } // 简写形式 export default new Vuex.Store({actions,mutations,state}) /* // 创建store对象(这个store对象是vuex插件中的老大,最核心的对象,这个对象store是用来管理actions对象、mutations对象、state对象。) const store = new Vuex.Store({ // 它是一个负责执行某个行为的对象 actions : actions, // 它是一个负责更新的对象 mutations : mutations, // 它是一个状态对象 state : state }) // 导出store对象(暴露之后,别人想用可以使用import进行引入) export default store */
//main.js import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false // 引入Vuex插件中的核心对象store import store from './vuex/store' new Vue({ el : '#app', // 一个全新的配置项,以前没有学过:store // 加上这个配置项之后,vm以及所有的vc对象上都会多一个属性:$store // 以后通过vm.$store或者vc.$store来获取store对象。 //store : store, store, render : h => h(App), })
Vuex配置项-getters
在Store.js里边写
拓展运算符。。。
拆括号,值得注意的是,拆了再加,会改变地址,不是原先那个。
可以用这种方法将相同的合并
Vuex内置对象-mapState映射State
这个对象能将State里的对象名与组件中的对象名联系起来,省去复杂的state调用
引用mapState
实际上实现是这样的
还记得上边的扩展...吗,他来了
V-model不能使用mapGetters,因为在text里设计到改值,必须要有set方法
mapAction和mapGetters
上边的savesUser分别对应函数名和action里对应的函数名,也是连接作用
Vuex模块化
在组件里想要使用state里的属性值有些变化
需要连点bModel,在点b
开启模块命名空间
由于在mutations里的函数可以自己去$store标签下找,没有了模块的束缚,这可能发送重名函数调用的风险。所以有了namespaced:true
这条指令开启后,以后访问都以“模块名/函数名”来访问
在mapaction和mapGetters等里还得加模块名参数
路由
实现单页面web,局部刷新,不需要跳转其他页面
路由工作原理
下载rout插件
导入路由
配置路由
使用路由
路由视图,起到一个占位的作用
多级路由
子路由
如果子路由写了‘/’,to后面不能带父路由
query传参方式
params方式传参
字符串形式
:用来表示传递的是参数,不是路径
字符串形式和对象形式
优化代码-props配置项,路由专属
props
浏览器的后退和前进
和栈有关,
声明式路由导航
编程式路由导航,按钮也能用
路由组件的销毁
可以在Keep-alive标签添加 include=‘组件名’
什么时候被销毁?
切换时被销毁
路由另外两个钩子
定时器
切到这个组件时激活activated切走的时候激活deactivated
路由多两个
路由守卫
本身就是在不同时机的不同位置添加代码
守卫是在切换组件之前查权,有没有权限访问这个组件
像过滤器一样
1.全局前置路由守卫
可以用一个布尔属性来鉴权,在对应的路由对象中使用meta属性来自定义属性
全局后置路由守卫
在创建router后,暴露前
前置后置
局部守卫
path
component
前端打包
详情请见p142
hash带#
#号后边是hash值,不会当做请求路径
history
刷新会将整个当做请求路径发送到服务器上
如何解决?
需要后端解决
在WEB-INF的web.xml里配置,当发生404报错时,自动跳转到index.html界面
Vue3
以前2是用vue-cli脚手架创建的,又开发了一个新的脚手架create-vue(vite)
更新
vite打包更快,启动服务器更快
简单回顾Vue2的响应式处理
Proxy底层
proxy底层使用了Reflect反射机制
setup中没有this
Vue3语法
setup函数
不用像以前一样写data,methods函数了,函数里可以获取到其他属性值,eg:name和age
setup还有个返回值,必须写
整体
渲染函数
正常在setup修改属性值不会有响应式
通过Vue3内置ref函数来实现响应式
RefTmpl对象中的Value属性具有响应式,底层使用了数据代理和数据劫持机制,也就是Vue2的响应式
替代品
.value会自动调用,不需要写,只写nameRefImpl即可
ref通常比较适合基本类型,reactive适合对象
reactive函数,专门用于对象类型响应式
reactive函数,生成响应式
可以对属性的增删改响应式,对数组也可以实现响应式
props
props不能随便修改,不需要return
Vue3生命周期
组合是在setup里写
Vue3全局事件总线
绑定
触发
清楚所有事件
解绑指定
计算属性computed
回顾一下Vue2
Vue3写法
计算属性
watch里边是proxy
ref数据
同时监视多个属性
感觉Vue3就是 let 函数名 = ?
watch
如果是监听对象的话可以这么写
一个箭头函数变化的细节影响了deep属性的启用
只有监视对象是属性时,oldValue才能拿到
当ref包装对象时如何监听
Vue3新增-watchEffect
组合式,直接在setup使用
比较像watch[数组]版,只要函数里边的内容有变化就会执行
Vue3自定义函数hook,为了实现代码复用
导入sum函数
自定义SUM函数
shallowRef
浅层次的响应式,就是没有响应式的效果,不会更改,在数据与原版没有区别
shallowReactive
只有第一层对象有响应式,第二次以后都没有了
readonly和shallowreadonly,深层只读,浅层只读
响应式数据判断
toRef和toRefs
为了使代码更加简洁,可以将对象省略比如data.counter在胡子语法里可以省略为counter,只能省略第一层
正常写不能成功建立响应式,需要以上两个函数
toRef
toRefs
研究一下Vue3中template标签如何解决可以有多个根标签的,应该是加了一个虚拟根节点吧
确实加了一个Fragment
可以将一个组件发送到指定的标签位置,达到远距离传送到效果
隔代数据传递
provide 提供 用于祖宗组件使用,实现数据传递
inject注入 用于子组件,也是响应式
有点像import和export
自定义ref
目标:输入后1秒在页面显示输入的Value
使用watch监听实现
使用自定义ref实现
Vue3中有一个自定义ref组件,你可以使用他来实现,
说一句防抖机制,避免大量信息爆发式输出,影响影响性能
好麻烦
Vue3小结-语法糖
setup可以写在script标签里,它将最外层的script标签当做以前setup的大括号
之前在setup外的component组件也不用写了,直接在标签里导入组件就可以了