vue相关知识点

vue中的MVVM模式

即Model-View-ViewModel。vue

Vue是以数据为驱动的,Vue自身将DOM和数据进行绑定,一旦建立绑定,DOM和数据将保持同步,每当数据发生变化,DOM会跟着变化。ios

ViewModel是Vue的核心,它是Vue的一个实例。Vue实例时做用域某个HTML元素上的,这个HTML元素能够是body,也能够是某个id所指代的元素。ajax

DOM Listeners和Data Bindings是实现双向绑定的关键。vue-router

DOM Listeners监听页面全部View层DOM元素的变化,当发生变化,Model层的数据随之变化;Data Bindings监听Model层的数据,当数据发生变化,View层的DOM元素随之变化。vuex

vue的生命周期

beforeCreate阶段: vue实例的挂载元素$el和数据对象data都为undefined,还为初始化。

created阶段:vue实例的数据对象data有了,$el尚未

beforeMount阶段:vue实例的$el和data都初始化了,但仍是挂载以前为虚拟的DOM节点,data还没有替换。

mounted阶段:vue实例挂载完成,data成功渲染。

beforeUpdate/updated阶段:
当data变化时,会触发beforeUpdate和updated方法。这两个不经常使用,不推荐使用。

beforeDestory/destoryed阶段:
beforeDestory是在vue实例销毁前触发,通常在这里要经过removeEventListener解除手动绑定的事件。实例销毁后,触发的destroyed。
复制代码

vue的数据双向绑定原理

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。json

具体步骤:axios

第一步:须要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter 这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化后端

第二步:compile解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图api

第三步:Watcher订阅者是Observer和Compile之间通讯的桥梁,主要作的事情是: 一、在自身实例化时往属性订阅器(dep)里面添加本身 二、自身必须有一个update()方法 三、待属性变更dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。缓存

第四步:MVVM做为数据绑定的入口,整合Observer、Compile和Watcher三者,经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变动的双向绑定效果。

组件中 data 为何是函数

由于组件是用来复用的,JS 里对象是引用关系,这样做用域没有隔离,而 new Vue 的实例,是不会被复用的,所以不存在引用对象的问题。

v-model是什么?怎么使用? vue中标签怎么绑定事件?

答:能够实现双向绑定,指令(v-class、v-for、v-if、v-show、v-on)。vue的model层的data属性。绑定事件:<input @click=doLog() />

v-show和v-if指令的共同点和不一样点?

v-show指令是经过修改元素的displayCSS属性让其显示或者隐藏

v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果

如何让CSS只在当前组件中起做用?

将当前组件的<style>修改成<style scoped>

<keep-alive></keep-alive>的做用是什么?

<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免从新渲染。

指令v-el的做用是什么?

提供一个在页面上已存在的 DOM 元素做为 Vue 实例的挂载目标.能够是 CSS 选择器,也能够是一个 HTMLElement 实例

自定义指令(v-check、v-focus)的方法有哪些?它有哪些钩子函数?还有哪些钩子函数参数?

答:全局定义指令:在vue对象的directive方法里面有两个参数,一个是指令名称,另一个是函数。组件内定义指令:directives

钩子函数:bind(绑定事件触发)、inserted(节点插入的时候触发)、update(组件内相关更新)

钩子函数参数:el、binding

Vue.js中ajax请求代码应该写在组件的methods中仍是vuex的actions中?

若是请求来的数据是否是要被其余组件公用,仅仅在请求的组件内使用,就不须要放入vuex 的state里。

若是被其余地方复用,这个很大概率上是须要的,若是须要,请将请求放入action里,方便复用.

computed 和 watch 的区别:

computed 是计算属性,依赖其余属性计算值,而且 computed 的值有缓存,只有当计算值变化才会返回内容。

watch 监听到值的变化就会执行回调,在回调中能够进行一些逻辑操做。因此通常来讲须要依赖别的属性来动态得到值的时候可使用 computed,对于监听到值的变化须要作一些复杂业务逻辑的状况可使用 watch。

Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

问题: obj.b已经成功添加,可是视图并未刷新

缘由:缘由在于在Vue实例建立时,obj.b并未声明,所以就没有被Vue转换为响应式的属性,天然就不会触发视图的更新,这时就须要使用Vue的全局api $set()

方法:$set()方法至关于手动的去把obj.b处理成一个响应式的属性,此时视图也会跟着改变了

Vue组件间的参数传递

父组件与子组件传值

父组件传给子组件:子组件经过props方法接受数据;

子组件传给父组件:$emit方法传递参数

非父子组件间的数据传递,兄弟组件传值

eventBus,就是建立一个事件中心,至关于中转站,能够用它来传递事件和接收事件。项目比较小时,用这个比较合适。

vuex是什么?怎么使用?哪一种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。

在main.js引入store,注入。新建了一个目录store,….. export 。

场景有:单页应用中,组件之间的状态、音乐播放、登陆状态、加入购物车 图片描述

state

Vuex 使用单一状态树,即每一个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不能够直接修改里面的数据。

mutations

mutations定义的方法动态修改Vuex 的 store 中的状态或数据。

getters

相似vue的计算属性,主要用来过滤一些数据。

action

actions能够理解为经过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操做数据。view 层经过 store.dispath 来分发 action。

const store = new Vuex.Store({ //store实例
      state: {
         count: 0
             },
      mutations: {                
         increment (state) {
          state.count++
         }
          },
      actions: { 
         increment (context) {
          context.commit('increment')
   }
 }
})
复制代码

vue-router

  1. 动态路由设置
const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})
一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,能够在每一个组件内使用。
复制代码
  1. 响应路由参数的变化

提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。由于两个路由都渲染同个组件,比起销毁再建立,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

复用组件时,想对路由参数的变化做出响应的话,你能够简单地 watch (监测变化) $route 对象:

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 对路由变化做出响应...
    }
  }
}
复制代码
  1. 路由导航钩子

全局前置守卫

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})
to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 必定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
复制代码

全局后置钩子

router.afterEach((to, from) => {
  // ...
})
复制代码

路由独享的守卫

你能够在路由配置上直接定义 beforeEnter 守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
复制代码

组件内的守卫

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 由于当守卫执行前,组件实例还没被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,可是该组件被复用时调用
    // 举例来讲,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 因为会渲染一样的 Foo 组件,所以组件实例会被复用。而这个钩子就会在这个状况下被调用。
    // 能够访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 能够访问组件实例 `this`
  }
}
复制代码
  1. 路由懒加载
结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

这就是如何定义一个可以被 Webpack 自动代码分割的异步组件。

const Foo = () => import('./Foo.vue')
在路由配置中什么都不须要改变,只须要像往常同样使用 Foo:

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
复制代码

axios(登陆拦截)

第一步: 路由 多添加一个自定义字段 requireAuth

path: '/repository',
name: 'repository',
meta: {
    requireAuth: true,  // 添加该字段,表示进入这个路由是须要登陆的
    },
component: Repository
复制代码

第二步:

router.beforeEach((to, from, next) => {
   if (to.meta.requireAuth) {  // 判断该路由是否须要登陆权限
       if (store.state.token) {  // 经过vuex state获取当前的token是否存在
           next();
       }
       else {
           next({
               path: '/login',
               query: {redirect: to.fullPath}  // 将跳转的路由path做为参数,登陆成功后跳转到该路由
           })
       }
   }
   else {
       next();
   }
复制代码

第三步

// 建立axios实例
let server=axios.create({
    baseURL: process.env.BASE_URL,  // api的base_url
    timeout: 5000  // 请求超时时间
})
// axios实例建立好以后,开始使用request拦截器对axios请求配置作统一处理,具体以下:
server.interceptors.request.use(config => {
    config.method === 'post'
        ? config.data = qs.stringify({...config.data})
        : config.params = {...config.params};
    config.headers['Content-Type'] = 'application/json';
    
    if (store.state.token) {  // 判断是否存在token,若是存在的话,则每一个http header都加上token
        config.headers.Authorization = `token ${store.state.token}`;
    }
    return config;
},error => {
// 返回错误处理
    Promise.reject(error);
});
// 而后是对response作统一处理
server.interceptors.response.use(response => {
    //这里根据后端提供的数据进行对应的处理
    if (response.data.result === 'TRUE') {
        return response.data;
    } else {
        //常规错误处理
    }
},error => {
    let text = error.response.status;
    switch (text) {
        case 401:
            // 返回 401 清除token信息并跳转到登陆页面
            store.commit(types.LOGOUT);
            router.replace({
                path: 'login',
                query: {redirect: router.currentRoute.fullPath}
            })
    }
 
    return Promise.reject(error)
})
复制代码
相关文章
相关标签/搜索