Vue 响应式原理
-
每个组件上都有一个相应watch实例
-
每个组件上都带有render函数
-
vue中使用object.definePropery劫持data中的数据
-
依赖收集:当页面上的render函数被执行时,会读取data上的属性,getter方法就会被调用,此时Vue会记录当前组件所依赖的所有data
-
当页面被触发时,data的中的数据就会改变,set方法就会被调用,此时Vue就会去通知当前组件上所依赖的所有data
总结:Vue采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调
Vue 生命周期
- vue一共有11个生命周期,常用的有8个,这个8个生命周期分为4个阶段
- 创建阶段
beforeCreate
created
- 挂载阶段
beforeMount
mounted
- 更新阶段
beforeUpdate
updated
- 销毁阶段
beforeDestroy
destroyed
创建阶段
- beforeCreate
在Vue实例初始化之后,此时初始化还未完成,什么都没有 - created
创建Vue实例初始化完成,data和methods已经可以用了,页面还没渲染
在这个阶段,只是初始化完Vue实例,页面什么东西都没有,可以使用data和methods
挂载阶段
- beforeMount
页面上没有真实的数据,只是一个模板 - mounted
el被新创建的vm.$el替换,并挂载到实例上之后,调用这个钩子函数,数据已经真实渲染到页面上了
在这个阶段,页面已经初始化完成
更新阶段
- beforeUpdate
数据更新时调用,这个时候页面上的数据还是旧的 - update
由于数据更改,导致Vistual Dom重新渲染和打补丁 在这之后调用该钩子函数,页面上的数据已经替换成最新的
在这个阶段,数据更新
销毁阶段
- beforeDestroy
实例销毁之前调用,Vue实例进入销毁阶段,但所有的 data 和 methods ,指令, 过滤器等都处于可用状态 - destroyed
实例销毁之后调用,此时这个组件已经被销毁,data,methods等都不可用
在这个阶段 实例被销毁
指令
- v-bind 用于响应式地更新html属性(就是绑定声明式变量)
- v-if 根据表达式值的真假来决定是否插入/移除元素
- v-on 用于监听DOM事件
- v-show 用于决定是否展示该元素,底层通过display:none实现
- v-html 在DOM内插入html内容
- v-for 循环
- v-text 渲染指定DOM的内容文本
- v-cloak和css规则 如[v-colak]{display:none}一起用,解决"一闪而过"问题
- v-model 双向绑定,用于表单,其本质是 @input 事件 和 v-bind:value
…
Vue中的v-if和v-show有什么区别
v-if和v-show看起来是差不多的,当条件不成立的时,其对应的元素就不可见
区别:
- v-if在条件切换时,会对标签进行适当的创建和销毁,而v-show则只是在初始化时加载一次,因此v-if的开销相对于v-show会大
- v-if是惰性的,只有在条件为真时才会真正的渲染标签,如果初始条件不为真,他不会渲染标签.v-show不管条件为不为真,初始化时都会渲染,它做的仅仅只是css样式的切换
Vuex
- Vuex的五大核心
- state 负责状态管理,用于存放数据,类似于Vue中的data,用于初始化数据
- mutation 专用于修改state中的数据,通过commit触发
- action可以处理异步,可以用来调接口,通过dispatch触发,不能直接修改state,首先在组件中通过dispatch触发action,然后在action函数内部commit触发mutation,通过mutation修改state状态值
- getter Vuex中的计算属性,相当于vue中的computed,依赖于state状态值,状态值一旦改变,getter会重新计算,也就是说,当一个数据依赖于另一个数据发生变化时,就要使用getter
- module模块化管理
- 辅助函数
- mapState,mapGetter,mapMutation,mapAction
state和getter中的数据,通过computed映射,mutation和action的方法通过methods映射//mapState computed:mapState([ //映射 this.count 为 store.state.count 'count' ]) <!-- 相当于 --> computed:{ count(){ return this.$store.state.count } } //其他类似
- Vuex流程
- 在vue组件里面,通过dispatch来触发actions 提交修改数据的操作
- 然后在通过action的commit来触发mutations来修改数据
- 然后在通过actions的commit来触发mutations来修改数据
- mutations接收到commit,然后修改state里面的数据
- 最后由store触发每一个调用它的组件的更新
Vuex的作用:项目数据状态的集中管理,复杂组件的数据通信问题
总结:Vue组件(action里面的dispatch)—>action(方法commit)–>mutations(Mutate)–>state(getter)—>store更新所有调用Vuex的组件(Vue component组件)
为什么Vue组件中的data必须是个函数
data对象为引用类型,当复用组件时,由于数据数据都指向同一个data对象,
当在一个组件中修改data时,其他复用的组件中的data会同时被修改,而使用返回对象的函数,
由于每次返回都是一个新的对象,引用地址不同,就不会出现这个问题
组件传值
- 父传子
- 通过props传递
//<!-- 父组件: -->
<child value='传递的数据' />
//<!-- 子组件 -->
props['value'],接收数据,接收之后,使用和data中定义的数据的使用方式一样
- 子传父
- 在父组件中给子组件绑定一个自定义事件,子组件通过$emit()触发该事件并传值
//<!-- 父组件 -->
<child @receive="receive" />
//<!-- 子组件 -->
this.$emit('receive','传递的数据')
可以通过v-model,v-model的本质就是@input=‘input’,input事件加上v-bind:value
- 兄弟组件传值
- 通过中央通信 let bus = new Vue()
//发送 methods:{ 函数{bus.\$emit('自定义事件名',数据)} } //数据接收 created(){ bus.$on('A发送过来的自定义事件名',函数) }
常用的事件修饰符
- .stop:阻止冒泡
- .prevent:阻止默认行为
- .self:仅绑定元素自身触发
- .once:只触发一次
- passive: 滚动事件的默认行为将会立即触发,不能和.prevent一起使用
- .sync修饰符
- .ref 用来获取DOM值,做DOM操作
路由
- 安装路由
npm install vue-router -S
- 使用
- 配置路由
-
首先导入组件
-
定义路由
const router=[
{path:'/home',component:Home},
{path:'/*',redirect:'/home'} //重定向
]
- 实例化Vue Router对象
const router = new ({routes})
- 挂载根实例
new Vue({
el:'#app',
router,
render:h=>(App)
})
- 在App.vue中使用路由
<router-view> </router-view>
- 定义动态路由,获取传过来的动态参数
> 在path属性加上/:id,使用router对象的params.id获取动态参数
- vue-router的钩子函数
> 常用的router.beforeEach(to,from,next),在跳转前进行权限判断
- 路由嵌套
>在一个路由中,path对应一个component,如果这个component需要根据不同的URL再加载其他的component,称之为路由嵌套
例:A组件现在需要根据不同的URL,加载B组件或C组件
//1.给A组件指定一个容器
<router-view></router-view>
//2.配置路由词典
{
path:'/a'
component:A,
children:[
{path:'/b',componet:B}
]
}
注意:在设置子路由,路由匹配规则依然是适用的,只不过路由地址为空和异常,要携带父组件的路由地址,如:/a/ /a/b
aixos
- aixos的get方法
export async function fetchAllGoods(params) {
try {
const { data } = await axios({
url: '',
method: 'GET',
params
})
return data
} catch (error) {
console.log(error);
}
}
- post方法
根据get和post请求方式的差异,所以请求传递的参数也不同,get使用params,post使用data,
export async function fetchAllGoods(data) {
try {
const { list } = await axios({
url: '',
method: 'post',
data
})
return list
} catch (error) {
console.log(error);
}
}
-
axios的拦截器
分为请求和响应拦截器
- 请求拦截器,在请求发送出去做一些事情,一般是配置对应的请求头信息(如:加token鉴权)
instance.interceptors.request.use(function (config) {
config.headers.Authorization=localStorage.getItem('token')
return config
}
- 响应拦截器,处理reponse的结果
axios.interceptors.response.use((response) =>{
let data = response.data
if(response.request.responseType === 'arraybuffer'&&!data.length){
reponse.date=0
}
})