Vue2

146 阅读4分钟

双向绑定原理

<!-- 结合数据劫持和发布订阅者模式来实现 -->

使用Object.defineProperty(target, key, decription)
在description中设置get和set属性
同时运用观察者模式实现wather,用户数据和view视图的更新

VueRouter跳转和 location.href有什么区别?

vue路由hash模式,是通过监听hashChange事件实现页面对应渲染

location.href跳转并刷新页面

路由守卫

<!-- 全局解析守卫 -->
  router.beforeResolve
  
<!-- 全局前置守卫 -->
  router.beforeEach((to, from, next)=>{next()})
  
<!-- 全局后置钩子 -->
  router.afterEach((to, from)=>{})
  
<!-- 路由独享的守卫 -->
  {path: '/foo',component: Foo,beforeEnter: (to, from, next) => {}} 
  
<!-- 组件内的守卫 -->
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  }
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  }
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }

vuex的使用

基础构成:
  state:存储数据;
  getters:派生数据,对state中的数据进行预处理;
  mutations:更新数据的方法;
  actions:调用mutations方法,更新state数据;
  plugins:实现配置
  
持久化存储方案:
  import VuexPersist from 'vuex-persist';
  const vuexLocal = new VuexPersist({
    storage: window.sessionStorage
  });
  plugins: [vuexLocal.plugin]
  
具体使用:
  1.可以把$store挂载在main.js根下面;页面this.$store使用state和方法;
    this.$store.phone;
    this.$store.dispatch('setPhoneSync',{phone:'111'})
    this.$store.commit('setPhone',{phone:'111'})
  2.页面引入API解构使用
  import {mapState,mapGetters,mapActions,mapMutations} from 'vuex';
  computed:{
    ...mapState({
      userInfo:'userInfo',
      phone:'phone',
    }),
  },
  methods:{
    ...mapActions({
      getPhoneSync:'getPhoneSync',
    }),
  }

MVC和MVVM

<!-- MVC -->
Model View Controller

<!-- MVVM  -->
Model View viewModel

Vue生命周期

beforeCreate:  进行数据和方法的初始化;
created: 已经完成数据和方法的初始化;
beforeMount:  开始渲染dom
mounted:可以渲染dom
beforeUpdate: data中的数据即将被更新;
updated:  data中的数据更新完毕;
beforeDestroy: 实例即将销毁;
destroyed:实例已被销毁;

data的值为什么是个函数

为了保证组件复用情况下data变量不被污染;每次都抛出一个全新的对象,隔离普通赋值

vue路由的几种模式

<!-- 由vue-router的mode属性控制 -->

hash: 
  使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
  监听hashChange事件,结合hashHistiry.push()和hashHistory.replace()
  
history : 
  依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
   通过pushState和replaceState方法实现;
   
abstract : 
  支持所有 JavaScript 运行环境,如 Node.js 服务器端。
  如果发现没有浏览器的 API,路由会自动强制进入这个模式.

vue中的事件修饰符

.prevent() 阻止默认事件;
.once() 只执行一次;
.stop() 阻止冒泡;

Vue中内置的组件

1. component组件
有两个属性---is  inline-template  渲染一个‘元组件’为动态组件,按照'is'特性的值来渲染成那个组件

2. transition组件
为组件的载入和切换提供动画效果,具有非常强的可定制性,支持16个属性和12个事件

3. transition-group
作为多个元素/组件的过渡效果

4. keep-alive
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们

5. slot
作为组件模板之中的内容分发插槽,slot元素自身将被替换

SPA

单页面应用,只有一个入口html文件,解析/a/b渲染对应内容模块

vue和传统页面/jquery的区别

<!-- vue -->
  主张数据驱动视图,
  不建议直接操作dom,
  设置this.$refs满足某些场景,
  实现了双向数据绑定;计算属性,监听属性等提升开发效率
  单页面应用
  虚拟dom和diff算法
  易懂和利于维护的生命周期

<!-- 传统js/jquery -->
  很多地方去操作dom,不断造成页面的回流重绘
  一般需要良好的代码习惯和规范才行,否则代码不利维护和阅读

computed & watch

<!-- computed -->
  寓意计算属性
  内部需要return语句
  只有依赖的值改变才会重新计算
  
<!-- watch -->
  寓意监听属性
  可以监听data的值和路由
  类似监听+事件回调

何时需要使用beforeDestroy

1. 在当前页面中使用了 $on 方法,那需要在组件销毁前解绑。
2. 清除自己定义的定时器
3. 解除事件的绑定 scroll mousemove

v-if & v-show

<!-- v-if -->
如果条件不成立不会渲染当前指令所在节点的 dom 元素

<!-- v-show  -->
会正常渲染,只是切换当前节点的CSS属性为display:none;

组件通讯

父子组件:
  父传子:通过v-bind传递props
  子传父:自定义事件,子通过$emit(EventName,data)触发
  
兄弟组件:
  1.可以先子传父然后再父传子。
  
无关系组件/兄弟组件:
  1.注册EventBus事件总线,监听一方使用EventBus.$on,传值一方使用EventBus.$emit
  2.使用vuex

v-model

实则是个语法糖,如inputv-model , 可以解析为:value和@input的结合

active-class是哪个组件属性

Vue-router模块中的router-link组件,设置激活时的样式。

vue-loader是什么?用途有哪些

解释:
  解析和转换.vue文件。提取出其中的逻辑代码 script,样式代码style,以及HTML 模板template,
  再分别把他们交给对应的loader去处理
  
用途:
  使得js可以写es6,style样式可以写scss或less

说明vue项目里的每个目录和文件

node_modules  //依赖库集合
src/assets  //文件夹是放静态资源;
src/components  //是放组件;
src/router  //是定义路由相关的配置;
src/view  //视图;
src/app.vue //是一个应用主组件;
src/main.js //是入口文件
.gitignore  //git提交忽略
.babelrc  //对预设(presets)和插件(plugins)进行配置

vue-router的动态路由

创建:path: '/details/:id'
取值:this.$route.params.id

vue路由跳转传参

<!-- 使用 name + params -->
  参数不会显示在地址栏
  刷新页面参数会丢失

<!-- 使用 path + query -->
  参数会显示在路径上
  刷新不会被清空

Vuex中actions和mutations的区别

<!-- Mutations -->
  更改是同步更改
  参数:(state,payload)
  用于用户执行直接数据更改
  页面使用store.commit('名')触发

<!-- Actions -->
  更改是异步操作
  参数:(context,payload)
  一般此类函数内用于发起接口请求或其他含副作用操作
  页面使用store.dispath('名')触发

axios的常用设置

// 公用接口前置地址
  axios.defaults.baseURL = domain;
// 请求超时时间
  axios.defaults.timeout = 60000;
// 设置请求头--返回类型
  axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
// post请求
  axios.post
// get请求
  axios.get
// 添加请求拦截器
  axios.interceptors.request.use((config)=>{
    // 在发送请求之前做些什么
    return config;
  },(error)=>{
    // 对请求错误做些什么
    return Promise.reject(error);
  });
// 添加响应拦截器
  axios.interceptors.response.use((response)=>{
    // 对响应数据做点什么
    return response;
  },(error)=>{
    // 对响应错误做点什么
    return Promise.reject(error);
  })

vue自定义指令

Vue.directive('custom-hasbtn', {
  inserted: function (el, binding) {
    el.parentNode.removeChild(el);
  }
})

keeep-alive的使用

<!-- 注:当keeep-alive内切换组件的时候会触发组件activated、deactivated生命周期 -->

一. 标签属性配置
      标签作用:
        缓存包裹的组件
      标签属性:
        include="ucenter,booklist"  表示当组件是ucenter,booklist才会被缓存
        exclude="ucenter,booklist"  表示当组件除了ucenter,booklist才会被缓存
二. 路由meta配置
      meta:{
        keepAlive:false // 不需要被缓存的组件
      } 

组件的注册

<!-- 全局注册:(多个组件可以使用vue.use()包裹) -->
  Vue.component('my-component-name', { /* ... */ })
  
<!-- 局部注册 -->
  import table from '../table/table';
  components:{
    mytable:table
  }

使用scss依赖模块

node-sass 和 sass-loader

dom循环绑定:key的作用

为了高效更新虚拟dom,节约计算时间

Vue的属性名称与method的方法名称一样时会发生什么问题

最好不要重复,重复会报错:<方法“xxx”已定义为数据属性>

vue为什么要求组件模板只能有一个根元素

整个项目只有一个index.html入口
vue需要生成虚拟domTree,根当然只能有一个
/* 这个问题在Vue3.0已经修复,支持多节点 */

v-if和v-for为什么避免一起用

因为v-for优先级大于v-if,这样循环中会造成不必要的计算浪费
/* 这个问题在Vue3.0版本已修复,官方做出优化 */

vue的过滤器

作用:处理数据

常用:时间格式化、千分符、数据过滤

<!-- 全局过滤器 -->
  Vue.filter('formatTime', function (value) {
    const date = new Date(val);
    const hour = date.getHours();
    const minutes = date.getMinutes();
    const seconds = date.getSeconds();
    return `${hour} : ${minutes} : ${seconds}`;

  })
<!-- 组件内过滤器 -->
  export default{
    name:'home',
    filters:{
      formatTime(val){
        const date = new Date(val);
        const hour = date.getHours();
        const minutes = date.getMinutes();
        const seconds = date.getSeconds();
        return `${hour} : ${minutes} : ${seconds}`;
      }
    }
  }

Vue表单修饰符

lazy:
  使用了这个修饰符将会从“input事件”变成change事件进行同步
  
number:
  这个number并不是限制用户的输入,而是将用户输入的数据尝试绑定为js中的number类型
  而如果用户输入的不是数字,这个指令并不会产生任何效果。
  
trim:
  可以用来过滤前后的空格

vue路由懒加载

1. vue异步组件技术
    {
      path: '/home',
      name: 'home',
      component: resolve => require(['@/components/home'],resolve)
    }
    
2. es提案的import()
    {
      path: '/home',
      name: 'home',
      component: () => import("@/components/HelloWorld")
    } 
    
3. webpack的require,ensure()
    {
      path: '/about',
      name: 'about',
      component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01')
    }

配置项目中404页面

path: '/*'  // 写在配置表最下面

Vue配置跨域代理

proxyTable: {
  /* 拦截以/api开头的请求 */
  '/api': {
      /* 指定目标域名端口 */
      target: 'http://localhost:8081',  
      /* 允许跨域 */
      changeOrigin: true,
      /* 重写这部分URL */
      pathRewrite: {
        '^/api': '/apiABC' 
      }
  }
}

vue切换页面的动画效果

结合transition标签实现

vue2和vue3的区别

1. proxy数据劫持代替object.defineProperty(优势:可以监听数组变化,可以直接修改对象属性等
2. Composition API,更好的逻辑复用和代码组织
3. 优化VirtualDom,使其编译更快,体积更小;
4. 更好的TypeScript支持,不再需要借助装饰器;

nexttick

定义:
  在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM
  
代码:
  this.box.height='200';
  Vue.nextTick(function () {
    // box已经渲染为 height=200 了,此事做些什么
  })

子组件可以修改props吗

答案:
  1. 不建议修改props,但是可以修改
  
如何修改:
  1. 如果props是字符串直接JS逻辑赋值修改会报错
  2. 如果props是对象可以使用【propsName】.【属性名】=【赋值】的JS语法修改
  3. 如果props用于表单,可以用 v-model 语法双向绑定,修改即生效