Vue

1.  v-model

v-model是一个语法糖, 实现在表单及元素上创建双向数据绑定, 真正靠的是:

1. v-bind绑定响应式数据

2. 触发@input事件并传递数据

 

2.  双向绑定原理

发布-订阅者模式 :它定义了对象间的一种一对多的依赖关系,只要当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

 

Vue2实现:

通过defineProperty劫持data的getter/setter

Get时,创建一个watcher

Set时,通知使用的watcher改变DOM

Vue2无法检测到对象属性的添加或删除,和数组的变化,这时候可用 vm.$set (object, propertyName, value)

 Vue3实现:

用Proxy这个对象来代替object.defineProperty实现数据的双向绑定,通过Proxy代理对象的方式来劫持数据,当数据发生变化时发出通知。

Proxy优势:

直接监听对象而非属性

直接监听数组的变化

拦截方式较多(有13种方式)

Proxy作为新标准将受到浏览器厂商重点持续的性能优化

 

3.  VueX

vuex是一种状态管理机制,将全局组件的共享状态抽取出来为一个store

state: state是存储的单一状态,是存储的基本数据。

Getters: 是store的计算属性,对state的加工, 类似computed,只有当它的依赖值发生改变才会被重新计算。

Mutations提交更改数据,使用store.commit方法更改state存储的状态。

Actionsstore.dispath像一个装饰器,提交mutation,而不是直接变更状态。建议把异步的操作放到这里来,mutation只做单纯的commit。

Module每个模块拥有自己的state、getters、mutations、actions。

Vuex提供了mapState、MapGetters、MapActions、mapMutations等辅助函数。

 

4.  Router

导航守卫:

路由跳转过程中的一些钩子函数。路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事儿的时机,这就是导航守卫。

router.beforeEach

router.afterEach

登录判断示例:

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requireAuth)){  // 判断该路由是否需要登录权限
    if(!sessionStorage.getItem('token') && !localStorage.getItem('token')){
      next({
        path: '/login',
        query: {redirect: to.fullPath}  // 将跳转的路由path作为参数,登录成功后跳转到该路由
      })
    }else{  next(); }
  }else {  next();  }
});
export default new Router({
    routes: [
        {
            path: '/',
            name: 'home',
            redirect: '/home'
        },
        {
            path: '/home',
            component: Home,
            meta: {
              title: '',
              requireAuth: true,  // 添加该字段,表示进入这个路由是需要登录的
           }
        }
    ]
})

 

单独路由守卫:beforeEnter

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

 

路由懒加载:

Webpack: 使用import

const Foo = () => import('./Foo.vue') 
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

Vite: 使用defineAsyncComponent

import { defineAsyncComponent } from 'vue'
const _import = (path) => defineAsyncComponent(
         () => import(`../views/${path}.vue`)
);
const routes = [
  {
    path: '/async-component',
    name: 'asyncComponent',
    component: _import('home'),
  }
];

 

 HashRouter 和 HistoryRouter:

原理:

hash路由:hash模式的工作原理是hashchange事件。当URL改变的时候,页面不会重新加载, 也就是单页应用了,当#后面的hash发生变化,不会导致浏览器向服务器发出请求, 通过触发hashChange事件, 监听hash值变化来实现更新页面部分内容。可以用window.onhashchange监听hash的变化。

对于hash模式会创建hashHistory对象,在访问不同的路由的时候,会发生两件事:
HashHistory.push()将新的路由添加到浏览器访问的历史的栈顶

HasHistory.replace()替换到当前栈顶的路由

history路由:

主要使用HTML5的pushState和replaceState这两个api结合window.popstate事件(监听浏览器前进后退)来实现的

pushState可以改变url地址且不会发送请求

replaceState可以读取历史记录栈,还可以对浏览器记录进行修改

使用方法:

// hash路由***************************
// 监听hashchange方法
window.addEventListener('hashchange',()=>{
     div.innerHTML = location.hash.slice(1)
})
// history路由************************
// 利用html5的history的pushState方法结合window.popstate事件(监听浏览器前进后退)
function routerChange (pathname){
     history.pushState(null,null,pathname)
     div.innerHTML = location.pathname
}
window.addEventListener('popstate',()=>{
     div.innerHTML = location.pathname
})

区别:

hash模式较丑,history模式较优雅

pushState通过stateObject可添加任意类型的数据到记录中,而hash只可添加短字符串

pushState可额外设置title属性供后续使用

hash兼容IE8以上,history兼容IE10以上

history模式需要服务器支持,需要后端配合将所有访问都指向index.html,否则用户刷新页面,会导致404

 

5.  组件间通信

父子:props/$emit

爷孙:provide/inject

兄弟:vuex/eventBus

 

6.  Keep-alive

keep-alive就是保持路由组件活跃,不会被destroy销毁掉,组件没有被销毁掉的话,组件上挂载的数据就还存在,所以状态就可以保留。

 

使用方式:

常用的两个属性include/exclude,允许组件有条件的进行缓存。

两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态

 

应用场景:

查看表格某条数据详情页,返回还是之前的状态,比如还是之前的筛选结果,页数等

填写的表单的内容路由跳转返回还在,比如input框、下选择拉框、开关切换等用户输入了一大把东西,跳转再回来不能清空啊,不能让用户再写一遍

 

7. 生命周期

beforeCreate: 当前实例创建之前,一般用于加载动画,比如创建一个菊花旋转。

Created: 表示当前实例创建完成,组件、属性等初始化完成,一般封装一个方法,比如从网络请求数据,触发回调,关闭beforeCreated中的菊花加载动画。

beforeMount: 表示将要挂载,页面仍未显示

mounted: 此时可以操作dom

beforeUpdate与update: 保持数据与页面的同步,会频繁触发,一般不要进行操作

beforeDestroy: 表示组件即将销毁,一般用于取消计时器等。

 

8. Ref

ref 被用来给元素或子组件注册引用信息, 引用信息将会注册在父组件的 $refs 对象上。

ref 需要在dom渲染完成后才会有,要在生命周期 mounted(){} 后调用,或者在 this.$nextTick(()=>{}) 中调用。

1. ref 加在普通的元素上,用this.ref.name 获取到的是dom元素

<div ref="englishAnalysis" class="usageChart"></div>
console.log(this.$refs. englishAnalysis);

2. ref 加在子组件上,用this.ref.name 获取到的是组件实例,可以使用组件的所有方法

<page-summary title="练习" ref="outsideComponentRef"></page-summary>
console.log(this.$refs.outsideComponentRef);

 

9. 如何动态引入静态资源图片

通用

1. 将图片转base64格式:小图片

2. 使用import引入图片:要约定好图片名称,会有很多v-if判断,更适合单个文件资源

Webpack:

使用require(src)动态加载

Vite:

1. 使用import.meta.url:本地可以,打包后路径会丢失,需要将资源放到public目录

new URL(`../assets/images/${url}`, import.meta.url).href

2. 使用import.meta.glob(懒加载)// 不知道为啥不能用了

const getAssetsFile = (url: string) => {
  const path = `../assets/images/home/${url}`;
  const modules = import.meta.glob("../assets/images/home/*");
  return modules[path].default;
}

 

10. Vue3 与 Vue2 区别

1. 生命周期:vue3没有created、beforeCreated,vue3 onUnmouted代替destoryed

2. Vue3 支持多个根节点

3. Vue3组合式API,可将同一逻辑的内容写到一起。Setup语法糖,书写更自由。

4. Vue3 提供 Suspense 组件,fallback里可以加载前做些事情,比如loading

5. Vue3 提供 Teleport 组件可将部分 DOM 移动到 Vue app 之外的位置。比如项目中常见的 Dialog 弹窗。

6. Vue2 响应式原理基础是 Object.defineProperty;Vue3 响应式原理基础是 Proxy。可以监听对象或数组

7. vue3虚拟DOM的diff算法增加静态标记,通过建立新旧节点的关系映射找到最长递增序列。一定程度地减少节点本身及其属性的比对。

8. Vue3在第一次渲染后可以缓存事件。

9. ts的支持和打包优化等

 

11. 异步组件Suspense

<Suspense>
        <template #default><router-view /></template>
        <template #fallback><div class="loading"></div></template> 
</Suspense>

使用场景:错误处理、路由加载、异步组件加载。

 

12.  虚拟DOM和Diff算法

虚拟dom:

通过JS的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点。比操作真实dom减少性能开销。

diff算法

Diff 算法会对比新老虚拟DOM,记录下他们之间的变化,然后将变化的部分更新到视图。

 

VUE和REACT的diff:

相同:两者都只比较同一级节点,复杂度为O(n),用key去区分追踪每个节点。

React: 从左到右,先删除,再移动节点

Vue2:对旧节点做个映射表,然后遍历新节点剩余,先找到不需要移动的相同节点,再找要移动的节点,然后移动过去,最后找不到相同的,就去创建新的节点,并删除多余的节点。是两边向中间比较,最后再统一删除。

Vue3: 通过打静态标记,对于不参与更新的元素,只会创建一次,在渲染时直接复用。建立新旧关系映射数组,然后找最长递增子序列的方式

posted @ 2023-10-31 23:15  h2303  阅读(43)  评论(0)    收藏  举报