Vue2 学习笔记
Vue实例和容器一一对应
提示❗❗❗❗❗
数据绑定
v-bind:/:单向绑定v-model:value/v-model:双向绑定;默认绑定value值
他有3个修饰符
lazy懒加载,失焦再...--
number控制传入data的值是数字型--
trim清除两边空格--
checkbox如果没有配置value值,那收集的就是checked值--
checkbox如果配置value值,初始值为数组就收集value组成的数组,不是数组收集checked值
v-model不要绑定传递过来的prop,不推荐绑定多个属性 v-bind="obj", obj 是一个对象 如:{id:"container", class:"box"}
动态绑定属性:<a :[attributeName]="url"> ... </a>
动态绑定事件 <a @[eventName]="doSomething"> (改变evevtName值后之前绑定的事件也被移除了,这里的 eventName 会被解析为 eventname,从而取得实例身上的 evenname值)
其他详情 https://cn.vuejs.org/guide/essentials/template-syntax.html#raw-html
$mount('#id')
vue实例.$mount('#id')指定为vue实例指定容器- 还可以
el和$el都不要,写配置template:{ '<div>...</div>' }
如果要换行需要用模板语法
由Vue所管理的函数不要用箭头函数,不然
this会指向window
数据代理
- 数据代理原理 为对象添加属性
事件绑定
v-on:/@定义事件默认传递参数event鼠标事件event.target是触发此事件的元素;- 如果要传递参数并保留
event,则@click=function(参数1,$event)
- 事件:
click点击;scroll滚动条滚动;wheel滚轮滚动;keydown键盘按下;keyup键盘起来
修饰符:(修饰符可连写)
prevent阻止默认事件stop阻止时间冒泡once事件只触发一次capture执行捕获模式self只有event.target是当前操作元素才触发passive事件默认行为立即执行,无需等待回调函数native执行vue定义的原生事件
按键别名:
enter回车delete删除esc退出space空格tab制表符up上down下left左right右caps-lock大小写转换(两个单词转换为短横线命名)
data中的数据会做数据代理所以不需要数据代理的放在其他配置项里面,如methods...
计算属性computed
- 原理:数据代理
- 完整写法:
- 简写:
如果计算属性只读,那就用简写方式
监视配置
监视完整写法:
handler其实就是监视的简写,接收两个参数新值与旧值
计算属性和监视:
- 监视可以完成异步操作
- 配置里的函数不能写箭头函数,不然
this指向是window,配置里的属性里的函数用箭头函数,this指向vm
绑定class样式:
:class="1 2 3"字符串绑定 适用确定且少:class="[1,2,3]"数组绑定 适用数量类名不确定:class="{1:true,2:false,3:true}"数量类名确定:class="{1:true,{2:true,3:false}}"数量类名确定
绑定style样式:
:style="{fontSize:'10px'}"对象绑定:style="[{},{}]"数组绑定
条件渲染
v-show隐藏节点,节点还在v-if隐藏节点,节点不在;v-if,v-else-if,v-else同理js代码中的条件判断,需要挨在一起template标签不能和v-show连用
遍历:
v-for="(item,index) in/of arr" :key=indexv-for="(value,key) in/of obj" :key=keyv-for="(number,index) in/of number" :key=indexv-for="(str,index) in/of str" :key=index
key原理:
- 没有啥逆序操作的时候用
index作为key是没问题的,其他最好用唯一标识
Vue检测数据改变原理(待完善)
- 构造函数中的
this就是用构造函数创建的实例对象 - 部分代码原理
Vue.set()方法
为实例数组/对象添加属性
对象
Vue.set(target,key,val)vm.$set(target,key,val)
数组
Vue.set(target,index,item)vm.$set(target,index,item)
target不能是vm或vm.data/vm._data即不能是根
他只能给data中的对象添加属性
数组的检测原理
Vue不会为数组元素添加响应式的getter和setter,所以通过下标更改数组数据是无法被Vue所监测到的。针对数组,只有通过调用push、pop、shift、unshift、splice、reverse、sort这7个改变原数组本身的API,才会引起Vue的响应- 直接赋值修改不行,但是
xx[index].key=xxx这样就行;xx[index]=xxx这样不行
过滤器fliter
- 管道运算符
|一次把前面的值传递给后一个作为参数--- dayjs(时间戳).format()转换时间戳为时间,格式自查在bootcdn官网
dayjs在线库链接<https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.3/dayjs.min.js>
指令
v-text内容以文本方式呈现v-html解析html语句(此方法不能用于用户输入区,容易引发xss攻击)v-cloak在Vue接管容器的时候这个属性会被Vue移除,可以用来在网速慢的时候先不展示容器v-pre,Vue跳过此节点
自定义指令:配置directives
全局指令配置:
Vue.directive('指令名',{})/Vue.directive('指令名',function(){})
directives配置里的属性的this是window,fliter里的也是
生命周期

mounted(){}与其他配置同级,挂载完后执行(真实DOM元素放到页面后执行)debugger;在代码里写这个就相当于在此处打了断点- 销毁后
Vue给Dom绑定的原生事件是还存在的 - 在
beforeDestory时候数据方法是可以访问修改的,但是不会触发更新
创建组件
- 定义=>注册=>使用
Vue.extend({})
若是组件标签名和组件名一样可以直接简写即
'hello':hello直接写成hello一个单词命名:首字母大小写都可;多个单词命名:用-连接或者每个单词首字母大写(首字母大写这个方法需要脚手架)
创建组件时可以不写
Vue.extend()直接组件名={...},这样写在注册组件时,Vue自动执行extend()还可以给组件配置
name属性让他在开发者工具中展示其他名字
组件的嵌套:组件中也有template配置
组件的原理:比如创建一个组件叫hello
- 组件本质是一个
VueComponent构造函数,在调用Vue.extend()时生成并赋值给hello Vue在解析组件时,会创建一个hello实例对象(也就是执行new VueComponent(option))- 每次调用
Vue.extend()都会返回一个全新的VueComponent - 其实此时
hello就相当于Vue,hello的实例对象vc就相当于vm,所以this的指向也就不言自知了
组件与Vue的内置关系

黄色线Vue改的,本来是指向Object.prototype
render函数
- 因为默认引用的
vue文件是精简版的,不包含模板解析器,所以不能写template:{},components:{};要用render函数代替 render函数的完整写法为
带runtime的是运行版本vue(没有模板解析器)
带common的是略(不知道)
带esm的意思是es6模块化语法用的
vue.config.js
- 在这个里面可以配置
vue的个性化,具体在vue-cli文档配置中现查现用即可 - 比如我在
vue.config.js中加lintOnSave:false那当我定义一个变量没有使用也不会报错了
ref属性
- 用来替代
id,具体引用如下
- 给元素添加
ref属性,会出现在实例的$refs属性上key是ref值,val是真实Dom元素
如果给组件添加ref属性,会获取到组件实例对象
props配置(子组件配置,父组件赋值)
props的三种写法:
<font style="color:#F5222D;">vue</font>不允许改<font style="color:#F5222D;">prop</font>值(<font style="color:#F5222D;">prop</font>值是只读的),有效果但不允许改,如果要在子组件改,在data中新配置一个参数接受传进来的<font style="color:#F5222D;">prop</font>值,改<font style="color:#F5222D;">data</font>中的数据
<font style="color:#F5222D;">prop</font>也可以实现子组件传递数据给父组件
先在父组件定义一个带参函数
然后把这个函数用<font style="color:#F5222D;">prop</font>传递给子组件
然后子组件调用这个函数的时候就可以用传参的方式让父组件得到子组件来的数据
mixin配置
- 组件之间复用配置
- 另外创建一个js文件,里面写
export default {data(){return{}}},在组件中配置mixin:[mixin]
如果组件中有的东西,则采用组件中的;
钩子函数都会采用
Vue.mixin({})全局混入
插件创建与使用
- 插件是一个对象,写在一个js文件中并导出
- 在main.js中使用插件
import plugin from './plugins';Vue.use(plugin) - 这样Vue就使用了这个插件,在其他组件中就可以使用插件中定义的过滤器,自定义事件...
scoped
css只控制自己
本地存储localStorage
setItem('key','value')添加一个键值对getItem('key')获取一个键的值removeItem('key')删除一个键值对clear()清除所有
这里面存储对象得是
json对象当对对象增删改查时,可以用监视来向本地存储更新数据,而且最好写完整写法进行深度监视
自定义事件
- 适用于子传父
绑定
- 第一种写法:用
@绑定事件再用this.$emit('事件名',参数1,参数2...)
- 第二种写法:在
mounted钩子中写this.$refs.hello.$on('sendMsg',this.showMsg)绑定事件再用this.$emit('事件名',参数)
如果
mounted中的this.showMsg直接写成了匿名函数,那这个函数的this指向vc如果写成箭头函数,
this指向vm!!!不建议这样写,建议如上图代码中这样写,先在
methods中配置好当在组件标签中写
vue本来就有的事件的时候他会默认为是自定义事件,从而触发失败这个时候就要用修饰符
native来修饰
第二种写法更好,更灵活,因为可以进行延迟,不用一开始就绑定事件导致函数还没准备好而触发失败
一个函数需要接收多个参数,
函数(参数1,...params){};//意思是拿第一个参数,其他参数打包在params数组中也可以用
$once绑定一次性事件,也可以用$on绑定然后用once修饰符绑定一次性事件
解绑$off()
$off('')解绑一个自定义事件$off(['',''])解绑多个自定义事件$off()解绑所有自定义事件
要写在定义自定义事件的组件里,即写
$emit的那个组件
全局事件总线$bus
$bus是自己命名的,并不是封装好的Api- 原理
- 在两个组件之间找到一个可以用
vm各种方法的中间者 - 一个组件给中间者绑定事件,规定回调
- 另一个触发事件
- 在两个组件之间找到一个可以用
- 代码实现
消息订阅与发布pubsub.js
- 所有框架适用
- 使用
- 安装
pubsub.js库:npm i pubsub-js - 在接受组件中订阅消息
let subId = pubsub.subscribe('消息名',回调函数) - 在发送数据组件中发布消息
pubsub.publish('消息名',数据)
- 安装
- 取消订阅
punsub.unsubscribe(subId);
在用了全局事件总线和
pubsub后最好在beforedestory钩子里取消事件绑定和订阅
$nextTick
- 改变代码执行顺序,在一个函数中用它,会让之前的操作做完并重新渲染
Dom后再执行它的回调 this.$nextTick(回调)
这是一个钩子函数
Vue实现动画
动画写法
- 如果要给全部的
transition标签包裹的元素执行动画则css中hello换成v appear默认执行一次
过度写法
多个过度
- 包裹在一个
transition-group标签中
这样写必须给每个子元素一个唯一的
key值
animate.css库
- 安装
npm i animate.css - 导入
import 'animate.css' - 给
transition标签配置name="animate__animated animate__bounce"enter-active-class="进入类名"leave-active-class="离开类名"
类名到官网或者css库复制
配置代理
vue-cli会自动启动一个代理服务器localhost:8080- 这个代理服务器的根文件就是
public文件夹
- 这个代理服务器的根文件就是
- 在
vue.config.js文件中开启代理服务器
- 开启一个服务器。用express举例
- 在
vue组件中用axios请求数据
安装
axios: npm i axios
express框架使用见ajax或node基础
❗开启代理服务器后需要重启vue
配置代理完整写法
- vue中这样请求
axios.get('http://localhost:8080/msg/one').then()
完整写法可以控制他是否走代理,如果不走代理,就默认给根文件的同名文件
v-resource
- 了解即可
- 安装
npm i v-resource - 引入
import xxx from 'v-resource' - 使用
Vue.use(xxx) - 然后
this.$http.get()等价与axios.get() resource封装的是xtr,axios封装的promise
插槽
默认插槽
- 子组件中写
slot标签 - 负组件中写插入内容
具名插槽
slot标签给个name属性并给值- 父组件中写给
v-slot指令添加设置好的name值 - 如果是用
template标签包裹的可简写v-slot为slot
作用域插槽
- 因为插槽是在父组件中解析了再插入子组件中,所以就读不到子组件的信息
- 插槽向父组件传值
slot标签绑定数据:msg='data中的数据'- 父组件中必须用
template标签包裹要插入的内容,并添加属性scope='val'- val即是子组件传来的值
- 使用时
{{val.msg}}
slot标签传递过去的是
{msg:data中的数据}即val
如果直接用msg别忘了解构赋值
vuex
多个组件共享状态(数据)
原理图

配置环境
- 安装
vuex3版本:npm i vuex@3❗ src目录下新建一个store文件夹,里面新建一个index.js
- main.js中引入store再配置
为什么use不写在
main.js里,因为import会先引入store再执行Vue.use(Vuex)
使用
- 需要用数据的组件中写
this.$store.dispatch('actions中的函数名',value)- 如果不需要发送
ajax之类的,可以直接用this.$store.commit('',xx)直接略过actions {{$store.state.sum}}组件中获取数据
- 如果不需要发送
- 配置文件
index.js添加
mutations中的函数最好全部大写
mapState与mapGetters
当在模板中用$store.state.数据,写太多的时候不好
- 方法一,配置计算属性一个一个定义计算属性
- 法二,用mapState直接映射
mapState({sums:'sum'})计算属性名为sums,值为state中的sum;返回值为{sums(){return ...}}- 所以用
...语法...mapState({sum:'sum',...})返回值为sum(){}就可以直接写在计算属性的配置里了 - 数组写法,需要计算属性名与
state中的属性名相同...mapState(['sum'])
mapActions与mapMutations
当用this.$store.dispatch('',),写太多的时候不好
- 用
mapState直接映射mapAction({adds:'add'})-----方法名为sum,值为state中的sum;返回值为{adds(){这里面会去联系dispatch并传参给它,第一个参数就是'add',第二个要在模板语法里传递}}- 所以用
...语法...mapActions({adds:'add',...})返回值为adds(){}就可以直接写在methods的配置里了 - 数组写法,需要方法名与
actions中的属性名相同...mapActions(['add'])
因为
dispatch和commit需要传递参数,所以在模板里传<button @click="adds(step)"></button>相当于
mapActions联系actions,把add函数赋值给adds,所以给adds传递参数,就相当于给actions中的add传递参数
vuex模块化
- 配置的时候这样写
namespaced:true
这个属性必须写,不然找不到
- 使用
- 第一种写法(不推荐)
上述state不可以像mapGetter这样写
-
- 第二种写法(推荐)
-
- 第三种写法(看着办)
nanoid
- 安装
npm -i nanoid - 引用
import {nanoid} from 'nanoid' nanoid()随机生成一段字符串id
路由
初级使用
- 安装
npm i router@3 <router-link to='/..' active-class=''></router-link>当<a></a><router-view></router-view>- 新建
router文档中的index.js
- main.js
路由组件最好在
src目录新建一个pages目录来存放
每个组件的$route属性值都是关于自己的
每个组件的$router都是一样的且是同一个东西
嵌套路由
- 配置与使用
子路由不写/
使用写全路径
query路由传参
- 传
- 接收
命名路由
- 当要写的路由路径太长才使用
- 配置
- 使用
params路由传参
- 配置
- 传
- 接收
❗❗❗
如果用params传递参数且用to的对象式写法,必须用name,不能用path
- params占位乐但是不传,那浏览器导航栏里的路径会出错,但是页面还是能跳转,刷新后就不能跳转了
- params传递空串也会导致与1同样问题,可以在配置的时候写params:{
data:''||undefinded
}
props传参数
- 在配置中给组件传递固定数据,对象传递,
query不行
- 第二种传法
这样会把所有
params参数以props的形式传递过去,使用时就不用$route.params.msg了
但是此方法不适用与于query
- 函数传递(推荐)
router-link的replace属性
替换当前浏览器纪录,默认为追加push
编程式路由导航
$router的apipush({}){}里的配置就和:to"{}"中的一样;追加记录replace({})同上;替代记录back()后退forward()前进go(2/-2)前进/后退2步
push({},()=>{},(error)={})完整长这样
push()会返回东西,不写回调会有警告,可重写push方法来一劳永逸
缓存路由组件
- 使路由跳转时组件不销毁
- 比如组件内有
input有内容,那么切换去其他组件再切换回来input内容不消失
- 比如组件内有
include的值为需要保留的组件name值;如果保留全部就不用写;如果保留多个:include="['','','']"
activated与deactivated
当一个组件内有input且组件内有定时器等不需要缓存的东西,就可以在deactivated生命周期中消除,这样组件能在不被销毁的同时缓存需要的东西
- 两个钩子函数
activated在组件激活时被触发deactivated在组件失活时触发
路由守卫
全局前置路由
- 路由配置中配置
路径中有参数的话,编译完成的路径才是
to或者from的path值
❗ 也可以不用比较path或者name,可以给已经知道需要守卫的路由配置一个值来判断是否需要验证
❗ 但是配置中不允许随便给属性,所以写在一个属性meta里,这个是专门给程序员自己定义数据用的,在$route里可以看见
全局后置路由
- 路由配置中配置
独享前置路由守卫
没有独享后置路由
组件内的守卫
- 通过路由规则进入才会调用,直接使用
<组件名/>不会调用 - 与
mounted配置同级
beforeRouterEnter(to,from.next){}- 进入组件后调用给❓(可能理解错了)
afterRouterEnter(to,from.next){}- 从此组件跳去其他组件后调用❓(可能理解错了)
- 使用
- 在组件里用,本质是钩子函数
路由守卫执行顺序
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave守卫。 - 调用全局的
beforeEach守卫。 - 在重用的组件里调用
beforeRouteUpdate守卫(2.2+)。 - 在路由配置里调用
beforeEnter - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter - 调用全局的
beforeResolve守卫(2.5+)。 - 导航被确认。
- 调用全局的
afterEach钩子。 - 触发
DOM更新。 - 调用
beforeRouteEnter守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入。
简单来说就是:beforeRouteLeave-->beforeEach-->beforeEnter-->beforeRouteEnter-->afterEach-->DOM更新-->beforeRouteEnter的next
全局前置-独享-组件内进入-全局后置-组件内离开
路由懒加载
- 语法
import('url')返回的是promise对象 - 所以可以在注册组件时候让组件的值为
promise对象,底层代码在遇到promise对象时会去取成功的值,具体实现源码见 - 在用户访问组件时才会加载
vue的两种工作模式
hash带#history不带#- 不是很懂
Vue项目打包
npm run build
element-ui入门
- 文档自查使用
!
babel.config.js中的presets配置项改为
其他
- v-module原理
- 自定义事件中的$event
- 修饰符sync语法糖
同步父子数据
- $attrs与$listeners
- $attrs 能获取到父组件传递来的 prop 参数
- $listeners 能获取到父组件传来的自定义事件
- 应用:比如二次封装element-ui组件,用传递prop,$attrs接收的形式改变组件样式
- $children与$parent
- $children获取当前组件的所有子组件,类型为数组
- $parent获取当前组件父组件(❓有多个父组件我没试过。。。)
各种报错解决集
- 关闭组件命名规则
- 关闭
html中报错clear
- 模块化getters的形参state,是$store下的一级state
- 给组件添加dom原生事件
- 最好创建完项目后,再用编辑器直接打开项目文件夹运行,让项目文件夹做根目录
常用包
- Lodash防抖节流...
- mockjs生成随机数据
- swiper轮播图库
- uuid随机生成id
- qrcode将文本生成二维码
- vue-lazyload图片懒加载
- vee-validate表单验证(烂)
规范
- 每个组件都放在一个各自的文件夹里与组件名相同,各自的资源也放各自文件夹里,按父子级关系创建文件夹
- src
src/components非路由组件src/pages路由组件src/router/index,js配置路由src/api/request.js对axios二次封装src/api/index.js对api同一管理src/mock/index.js假数据文件src/store/vuex文件src/icon/svg矢量图src/layout/❓一些组件和minixsrc/utils/重写push,二次封装axios,token...工具类
- 根
build/index.jswebpack配置文件- .env.development开发环境配置
- .env.production生产环境配置
- .env.staging上线环境配置
经验
- 多次操作的标签优先v-show
- 事件委托+自定义属性应用
- 用
代替组件根元素