![d64900da3bf1ab28f91d842f88ee4e58.png](https://i-blog.csdnimg.cn/blog_migrate/d371e9b9b0fb2c29904e937ed50546ff.png)
组件
vue中组件的注册方式分为两种
1.全局注册
import Vue from 'vue';
Vue.component('gl-nav',{//第一个参数是组件的名字
template:'<button>{{name}}</button>',//指向组件对应的模板
data:()=>{
return {
name:'cmy',
i:0
}//用来定义数据
},
props:{
//接受对应的传参
},
computed:{
//计算属性
},
watch:{
//监听属性发生变化
name(newdata,olddata){
//接受两个参数,第一个是改变后的值,第二个是之前的值
}
}
methods:{//相应的方法
add(){
this.name+=this.i+1;
}
}
...
})
全局注册的组件在任意组件中都可以调用的到,但是很多时候我们注册组件只需要他在父组件里面调用就可以了,所以全局组件适合注册一些基础的,通用的,可重复利用的组件
全局注册组件必须在根vue实例化之前发生
2.局部注册 在vue里面最常见的方式就是创建单文件组件
<template>
//主要用来渲染模板
</template>
<script>
//写组件的结构,通过export default 抛出一个对象
export default {
data () {
return {
}//定义数据
},
props:{
//接受对应的传参
},
computed:{
//计算属性 需要有返回值
},
watch:{
//监听属性发生变化 可以监听到data,props,$route路由的变化
name(newdata,olddata){
//接受两个参数,第一个是改变后的值,第二个是之前的值
}
//如果要监听的是一个对象的话只能挨个监听他们的属性
'opt.name'(newsata,olddata){
}
}//可以通过let key = this.$watch('key',(n,o)=>{
...//要做的事情
})
key()//取消监听
methods:{//相应的方法
add(){
}
}
}
</script>
<style scoped>//这个属性可以对组件的样式做模块化处理
//用来写组件的样式
</style>
单文件组件里面有一个
- <template> 主要用来做模板
- <script> 组件的结构
- <style> 组件的样式上面的scoped可以对组件的样式做模块化处理,还可以根据lang属性去选择使用的语言
除了全局组件,每一个组件的使用都需要通过import 将组件引入,然后通过components注册,之后才可以使用这个组件。 局部注册的组件只能哪里引入哪里用。
组件的生命周期
vue中组件的生命周期分为
- 初始化阶段(主要做数据初始化)
- beforeCreate data和watch还没有被调用
- created 主要做了data,$watch,props,methods,$event方法的实例
- DOM挂载阶段
- beforeMount 主要做组件的渲染,在挂载之前被调用
- mounted 可以做组件的dom操作,也就是可以获取到$el属性(挂载到的dom元素)
- 更新阶段(当组件中修改了某一数据去重新触发渲染的时候触发)
- beforeUpdate 数据更新的时候调用,这时候dom还没有重新渲染
- updated dom重新渲染之后会调用,所以现在可以执行依赖dom的操作了,但不应该在这个生命周期更改状态,会触发死循环,如果要改变状态可以使用计算属性或者watch监听来实现 updated生命周期的时候子元素有可能还没有被重新渲染,如果希望视图重绘完毕之后可以使用this.$nextTick this.$nextTick().then(//DOM更新之后执行)//返回值是一个promise 如果浏览器不支持promise自行解决
- 卸载阶段
- beforeDestroy 组件卸载之前被调用 实例销毁之前调用一次,这时候实例还是可用的
- destroyed 组件卸载的时候会被执行,组件的指令包括事件进行解绑,数据,包括dom挂载的那些事件都会被销毁,但不会移除咱们用原生dom方法添加的事件,也不会移除setTimeout,setInterval这种定时器,如果有类似的操作就需要在这个生命周期中进行手动销毁
- 如果缓存启用的时候会有
- activated keep-alive组件激活时调用
- deactivated keep-alive组件停用时调用 组件的销毁阶段永远不会执行 模拟了一个组件销毁 但并不是真正的组件销毁
- 新增了错误处理生命周期
- errorCaptured 当捕获到一个来自子孙组件的错误的时候被调用错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
单页面路由
单页面路由指的是只有一个页面,但是有多个路由的应用,不向服务器发起请求,所有的路由跳转都是通过前端来控制,通过前端获取url的改变获取对应的路由进行页面的重新渲染。
优点
1. 页面跳转是异步加载的,不需要重新刷新页面,所以浏览器响应比较快一些
2. 页面进行跳转的时候还可以加一些动画的效果
3. 单页面路由改变的时候会存留历史记录,而且不会向后台发送请求
单页面路由需要具备的条件
- 路由会发生改变
- 不会向后台请求数据
- 浏览器存留历史记录
单页面路由一般分为两种模式
hash
hash利用的是url#的原理,就像咱们说的锚点链接,点击会触发url的改变,而且会存留历史记录,但是不会向后台发起请求。可以通过hashChange事件监听到路由的变化,获取到路由改变的地址,通过地址查找到对应的组件,进行渲染。
history
history利用的是浏览器新增的historyAPI中的pushState和replaceState方法做路由的改变并且存留历史记录,通过window.onpopstate监听路由的改变,根据对应的路由取到对应的组件进行页面的渲染
Bug
刷新页面的时候走的时候后端的路由,所以在后端进行一个配置,将前端所有的单页面路由指向index.html路由,这样就不会造成404的问题了。
vue组件中methods,watch,computed的区别
methods
主要用来做方法的定义 都是一个对象,调用一次就会执行一次,当依赖的值发生改变的时候会重新触发一遍。方法需要调用
watch属性监听
不需要返回值 监听的是data里面的数据(包括props,$route路由变化)里面的数据,定义的属性接受两个参数,第一个参数是新值,第二个参数是旧值,没有返回值 只要值发生变化 肯定会执行
computed 计算属性
通过某些属性的计算得到一个返回值,计算属性会对值进行缓存,只有当依赖的值发生改变的时候才重新触发一遍 主要用他代替了过滤器的功能,可以将一个值转换为另一个值 必须有返回值
应用场景
当我们要对某些属性进行一些复杂逻辑的时候,直接作用在template模板上会显的很乱,这时候就要考虑使用计算属性了。 计算属性设置的时候是以key和value的方式进行设置的,value的类型可以分为两种
- 默认为getter方法(function)
必须要有返回值,相当于函数作用在了这个计算属性的getter方法上
- 但是也可以设置setter(Object)
set方法没有返回值,设置set的时候只需要写this.comp='cmy'就会触发 如何使用
computed : {
add : function () {
return this.i*10
},
comp : {
get : function () {
return this.i+10
},
set : function (v) {
this.i =v;
}
}
}
计算属性只有当他们依赖的值发生改变的时候才会再次触发,否则读取的就是缓存里面的值,如果不想有缓存的话可以通过在methods里面定义方法,每一次调用都会重新触发改变。
组件和组件之间的通讯
vue中组件和组件之间的通讯指的是一个组件和多个组件之间的数据传递
- 主要有几个场景
- 子父通讯: 指的是父组件使用子组件的数据
有好多种方法可以实现,但最常用的是使用自定义事件,- 自定义事件 在组件上面通过v-on去绑定一个事件,事件的值是一个回调函数,回调函数里面接受参数,接受的参数是通过子组件传递过来的。通过子组件当中的$emit去触发自定义事件的名称,之后传递值,把属性传递到父组件上,父组件就可以获取到子组件的数据
- 获取实例的方式 父组件里面获取子组件的实例有两种方式
- 通过ref来获取 在组件中通过this.$refs.属性名就可以获取到子组件实例
- 通过$child来获取到当前组件里面所有的子组件,但$child是一个数组,没有办法获取到某一个指定的子组件,所以一般用ref来获取子组件实例
- 子父通讯: 指的是父组件使用子组件的数据
最推荐使用的就是自定义事件
- 父子通讯: 指的是子组件使用父组件的数据
- props 常用的是props 属性的形式传递给子组件数据,子组件
- 子组件里面利用$parents获取父组件实例
之后拿到父组件里面的数据,但这里面有一个约定俗成的规定,vue是单向数据流,默认是子组件不可以改变父组件的数据,尽量保持vue中单向数据流的概念,只能在原组件中改变数据
- 同级 就是两个同级之间的通讯 A组件使用B组件的数据。
- 代理 最明确的方式就是通过共同的父组件做一个代理,传递到另一个子组件中去,通过代理的形式,
- 自定义事件的形式 咱们可以写一个空的vue实例,在vue中有$on,$emit可以做自定义事件的处理,在a组件中使用$on定义事件,在b组件中通过$emit去触发,当然定义事件和触发事件要绑定在同一实例上,也就是咱们常说的发布订阅模式 eventbush 跨级 可能abc组件是一个层级关系,如果层级少的话咱们可以逐层传递,但是层级传递过多的话就会太麻烦了,我们就可以使用自定义事件的形式,也就是使用eventbush
如果涉及到更加复杂的数据通讯,或者很多组件都使用到这个数据,咱们可以将组件中的数据绑定在组件的根实例上,然后在组件中通过$router去访问,也可以使用vuex,因为vuex是全局的数据存储,在任何组件中都可以访问的到
$router和$route的区别
$router是路由实例
$route是当前页面的路由信息对象,包括路由的名称,路由的path,路由的参数,params,hash
$router是路由的实例,有一些操作路由的方法,$route是$router的一个属性的一个指针相当于,是$router.currentRoute
常用的实例属性
this.$el vue实例使用的根元素
this.$root 当前组件树的根实例,如果没有根实例 指向自己
实例方法
this.$set
this.$watch
用来进行监听,再调用一次是取消监听
this.$delete 删除某个不被监测到的属性
实例方法
this.$nextTick 当所有的组件更新完成之后延时调用 this.$nextTick().then(//dom更新后执行的动作)
常用指令
v-text 输出文本 v-html 输出标签 v-show 切换display属性 v-if 如果为真就渲染 是惰性的 如果初始化的时候条件为假就什么都不做
如果和v-for一起使用的话,v-for拥有更高的优先级
v-else 前面必须有v-if或者v-else-if v-for 循环 v-on @监听事件
修饰符
.stop - 调用 event.stopPropagation()。 阻止冒泡
.prevent - 调用 event.preventDefault()。阻止默认事件
.capture - 添加事件侦听器时使用 capture 模式。事件捕获
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.native - 监听组件根元素的原生事件。给组件添加事件的时候
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
v-bind 动态监听变化
修饰符
.sync 子父通讯的时候需要
v-model 受控组件 有三个修饰符 .lazy 取代input监听change事件 .number 把字符串转为数字 .trim 去除首尾空格 v-once 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
特殊特性
is 组件上的is属性发生改变的时候,组件也会跟着改变
ref
用来给元素或者组件添加引用信息,分为两种情况
- 作用在组件上 获取到的是这个组件实例
- 作用在dom元素上 获取到的是对应的dom元素
vue中的数据监测原理
vue中的数据如果想实现响应式更新渲染视图的话,必须将数据定义在data里面才可以实现,因为vue会给data里面定义的数据自动注入getter和setter方法,监听他们的变化,随时更新视图,利用的是ES5的Object.defineProperty方法来完成的 其中需要注意的是如果this.data中的数据没有出现在模板中,那么数据的改变将不会触发update生命周期,还有如果直接通过下标或者属性来改变this.data里面的数据的话通常会监听不到变化,这时候可以利用深拷贝或者$set方式改变数据,触发vue去监听到数据的变化 订阅发布加 数据劫持
如果向子组件绑定自定义属性 如果不被子组件props接受 就会成为这个组件的自定义属性
说一下vuex吧
vuex是适合于vue的状态管理工具,可以对vue中的状态进行统一的管理,避免了组件通讯层级过多的问题,vuex主要分为
- state 里面用来定义vue中的数据结构,在这里设置数据的初始值
- mutations 这里是唯一允许改变state的地方
- active 异步的操作需要放在这里面,否则监听不到变化
- getter 这里面用来进行过滤,不修改原数组
优点:
- 对于数据的管理是有固定规则的
- 可以同步视图进行更新
缺点:
- 对于状态操作的时候,读取对象层级过多
- 不能存储大量的数据
vue中的路由如何传递参数
- paramse 动态路由(必传)
- query参数传递(选传) 传递方式有两种
- router-link :to
- 通过vue实例的$router方法进行传参
vue路由的钩子函数
beforeEach 接受三个参数 to,from,next
afterEach 不能对路由做出改变
如何配置路由
new 一个vueRouter,之后里面传入配置参数,mode:'history/hash',routes:[{ path:'/',name:'dd',children:[],component:模板,meta }] 如果想要一个路由渲染不同的页面,可以将components设置为{default:comA,a:first,b:secend} <router-views name='a'/> 如果渲染default的话就什么都不用写
重定向
可以设置为字符串/bar ,也可以设置为name{name:'bar'},也可以设置为函数,返回值为字符串和对象
路由别名
alias 可以为路由设置别名 字符串,当访问别名的时候访问的也是当前路由
###vue中设置反向代理是在config下的index.jsdev下的proxyTable中配置的
设置别名访问路径 @ webpack中的reslove里面的alias属性可以用来配置路径别名
vue懒加载插件 vue-lazyload
这篇文章是18年找工作的时候总结的,现在显然已经有点过时了,但仍是有借鉴意义的。等过段时间会重新整理更新,可先马后看。如果文章有什么错误,或者我写的不明白的地方,欢迎与我私信,批评指正。