Vue 基础二(进阶使用)

一、Vue的响应式系统

(一)Vue 响应式的原理

Vue 的核心特性之一是响应式数据绑定系统。它允许我们轻松地将数据与视图进行绑定,当数据发生变化时,视图会自动更新。Vue 内部通过 Object.definePropertyProxy 来实现这一特性。

  1. Object.defineProperty

    • 在 Vue 2.x 中,Vue 使用 Object.defineProperty 来劫持对象的属性。

    • 当我们访问或修改被 Object.defineProperty 定义的属性时,Vue 会触发相应的 getter 和 setter 方法。

    • Getter 用于读取属性值并追踪依赖,Setter 用于设置属性值并通知视图更新。

  2. Proxy

    • 在 Vue 3.x 中,Vue 使用 Proxy 来实现响应式系统。

    • Proxy 提供了更强大和灵活的拦截机制,可以拦截对象的所有操作,包括属性的读取、设置、删除等。

    • Object.defineProperty 相比,Proxy 能够更高效地实现深度响应式。

(二)响应式 API

Vue 提供了一系列响应式相关的 API,用于手动创建响应式对象或追踪数据。

  1. ref :用于创建一个响应式的引用,返回一个包含值的 ref 对象。

JavaScript复制

复制代码
import { ref } from 'vue';

const count = ref(0);
console.log(count.value); // 0
  1. reactive:用于将一个普通对象转换为响应式对象。

JavaScript复制

复制代码
import { reactive } from 'vue';

const state = reactive({
  count: 0
});
console.log(state.count); // 0
  1. computed:用于创建一个计算属性,基于响应式依赖,自动追踪依赖并缓存计算结果。

JavaScript复制

复制代码
import { ref, computed } from 'vue';

const firstName = ref('John');
const lastName = ref('Doe');

const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`;
});
console.log(fullName.value); // John Doe
  1. watch:用于监听响应式数据的变化,并执行回调函数。

JavaScript复制

复制代码
import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newVal, oldVal) => {
  console.log(`count 变化了:从 ${oldVal} 变为 ${newVal}`);
});

二、Vue 生命周期

Vue 组件有一个完整的生命周期,从创建到销毁,会依次调用一系列的生命周期钩子函数。以下是 Vue 生命周期的主要钩子函数:

  1. beforeCreate

    • 在实例初始化之后,数据观测和事件配置之前被调用。

    • 此时,datamethods 等属性尚未初始化。

  2. created

    • 在实例创建完成后被调用。

    • 此时,datamethods 等属性已经初始化完毕,可以访问和操作。

  3. beforeMount

    • 在挂载开始之前被调用。

    • 此时,模板已经编译完成,但尚未挂载到 DOM 上。

  4. mounted

    • 在实例挂载完成后被调用。

    • 此时,DOM 已经渲染完成,可以进行 DOM 操作。

  5. beforeUpdate

    • 在数据更新之前被调用。

    • 此时,数据已经更新,但 DOM 尚未更新。

  6. updated

    • 在数据更新完成并重新渲染 DOM 后被调用。

    • 此时,可以重新操作 DOM。

  7. beforeUnmount

    • 在实例销毁之前被调用。

    • 可以在此清理资源,如定时器、事件监听器等。

  8. unmounted

    • 在实例销毁后被调用。

    • 此时,Vue 实例已经完全销毁,无法再进行操作。

三、Vue 的组件

(一)组件的基础知识

  1. 组件的注册

    • 全局注册 :使用 Vue.component 注册的组件可以在全局范围内使用。

JavaScript复制

复制代码
Vue.component('my-component', {
  template: '<div>This is a global component</div>'
});
  • 局部注册:在单个 Vue 实例或组件中注册的组件。

JavaScript复制

复制代码
const AppComponent = {
  template: '<div>This is a local component</div>'
};

const app = new Vue({
  components: {
    'my-component': AppComponent
  }
});
  1. 组件的通信

    • 父组件向子组件传递数据 :通过 props

vue复制

复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component :message="parentMessage"></child-component>
  </div>
</template>

<script>
export default {
  data() {
    return {
      parentMessage: 'Hello from parent'
    };
  }
};
</script>

vue复制

复制代码
<!-- ChildComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true
    }
  }
};
</script>
  • 子组件向父组件传递事件 :通过 $emit

vue复制

复制代码
<!-- ChildComponent.vue -->
<template>
  <div @click="$emit('child-event', 'Hello from child')">Click me</div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('child-event', 'Hello from child');
    }
  }
};
</script>

vue复制

复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component @child-event="handleChildEvent"></child-component>
  </div>
</template>

<script>
export default {
  methods: {
    handleChildEvent(message) {
      console.log(message); // Hello from child
    }
  }
};
</script>
  1. 动态组件 :使用 <component> 标签和 is 属性动态切换组件。

vue复制

复制代码
<template>
  <div>
    <button @click="currentComponent = 'ComponentA'">Show A</button>
    <button @click="currentComponent = 'ComponentB'">Show B</button>
    <component :is="currentComponent"></component>
  </div>
</template>

<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
  components: {
    ComponentA,
    ComponentB
  },
  data() {
    return {
      currentComponent: 'ComponentA'
    };
  }
};
</script>

(二)组件的高级特性

  1. 插槽(Slots):插槽允许父组件向子组件传递自定义内容。

    • 默认插槽

vue复制

复制代码
<!-- ChildComponent.vue -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

vue复制

复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component>
      <p>This is inserted into the slot</p>
    </child-component>
  </div>
</template>
  • 具名插槽

vue复制

复制代码
<!-- ChildComponent.vue -->
<template>
  <div>
    <slot name="header"></slot>
    <slot name="content"></slot>
  </div>
</template>

vue复制

复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component>
      <template v-slot:header>
        <h2>Header</h2>
      </template>
      <template v-slot:content>
        <p>Content</p>
      </template>
    </child-component>
  </div>
</template>
  • 作用域插槽

vue复制

复制代码
<!-- ChildComponent.vue -->
<template>
  <div>
    <slot :user="user"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: { name: 'John' }
    };
  }
};
</script>

vue复制

复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <child-component v-slot:default="slotProps">
      <p>{{ slotProps.user.name }}</p>
    </child-component>
  </div>
</template>
  1. 动态组件与缓存 :使用 keep-alive 缓存动态组件,避免重复渲染。

vue复制

复制代码
<template>
  <div>
    <keep-alive>
      <component :is="currentComponent"></component>
    </keep-alive>
  </div>
</template>
  1. 异步组件:允许组件以异步的方式加载,提高首屏加载速度。

JavaScript复制

复制代码
const AsyncComponent = () => ({
  component: import('./AsyncComponent.vue')
});

四、Vue 的状态管理

(一)Vuex 简介

Vuex 是 Vue 官方的状态管理库,用于集中管理Vue 应用中的状态。

  1. 安装 Vuex

bash复制

复制代码
npm install vuex --save
  1. 基本使用

JavaScript复制

复制代码
// store.js
import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
});

export default store;
  1. 在组件中使用 Vuex

vue复制

复制代码
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="incrementAsync">Increment Async</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.state.count;
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment');
    },
    incrementAsync() {
      this.$store.dispatch('incrementAsync');
    }
  }
};
</script>

(二)Vuex 的核心概念

  1. State:存储应用的状态数据。

JavaScript复制

复制代码
state: {
  count: 0
}
  1. Getter:类似于计算属性,用于从 state 中派生出一些状态。

JavaScript复制

复制代码
getters: {
  doubleCount: state => state.count * 2
}
  1. Mutations:用于改变 state 的唯一方式,必须是同步操作。

JavaScript复制

复制代码
mutations: {
  increment(state) {
    state.count++;
  }
}
  1. Actions:用于提交 mutations,可以包含异步操作。

JavaScript复制

复制代码
actions: {
  incrementAsync({ commit }) {
    setTimeout(() => {
      commit('increment');
    }, 1000);
  }
}

五、Vue Router

Vue Router 是 Vue 官方的路由管理器,用于实现单页应用中的页面跳转。

(一)安装 Vue Router

bash复制

复制代码
npm install vue-router --save

(二)基本使用

JavaScript复制

复制代码
// main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import Home from './components/Home.vue';
import About from './components/About.vue';

Vue.use(VueRouter);

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
];

const router = new VueRouter({
  routes
});

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

(三)路由导航

vue复制

复制代码
<!-- App.vue -->
<template>
  <div>
    <nav>
      <router-link to="/">Home</router-link>
      <router-link to="/about">About</router-link>
    </nav>
    <router-view></router-view>
  </div>
</template>

(四)路由参数

JavaScript复制

复制代码
// routes.js
{ path: '/user/:id', component: User }

// User.vue
export default {
  computed: {
    userId() {
      return this.$route.params.id;
    }
  }
};

(五)路由守卫

JavaScript复制

复制代码
// 全局前置守卫
router.beforeEach((to, from, next) => {
  // 在渲染该组件的对应路由之前调用
  console.log('beforeEach');
  next();
});

// 全局后置守卫
router.afterEach((to, from) => {
  console.log('afterEach');
});

// 路由独享守卫
const Home = {
  template: '<div>Home</div>',
  beforeEnter(to, from, next) {
    console.log('beforeEnter Home');
    next();
  }
};

六、Vue 的 Mixins

Mixins 是一种分发 Vue 组件中可复用功能的灵活方式。它允许我们将多个组件共用的逻辑提取到一个对象中,然后在多个组件中使用。

JavaScript复制

复制代码
// mixin.js
export const myMixin = {
  data() {
    return {
      message: 'Hello from mixin'
    };
  },
  created() {
    console.log('Mixin created');
  },
  methods: {
    myMethod() {
      console.log('Mixin method');
    }
  }
};

在组件中使用 Mixin:

JavaScript复制

复制代码
import { myMixin } from './mixin.js';

export default {
  mixins: [myMixin],
  created() {
    console.log('Component created');
  }
};

七、Vue 的插件

Vue 的插件可以扩展 Vue 的功能,通常用于全局功能的添加,如添加全局方法或属性、注册组件等。

JavaScript复制

复制代码
// myPlugin.js
export default {
  install(Vue, options) {
    // 添加全局方法
    Vue.myGlobalMethod = (message) => {
      console.log(message);
    };

    // 添加实例方法
    Vue.prototype.$myMethod = (message) => {
      console.log(message);
    };

    // 注册全局组件
    Vue.component('my-component', {
      template: '<div>This is a global component</div>'
    });
  }
};

在项目中安装插件:

JavaScript复制

复制代码
import Vue from 'vue';
import MyPlugin from './myPlugin.js';

Vue.use(MyPlugin);

八、Vue 的过渡与动画

Vue 提供了过渡和动画的支持,可以轻松地为 DOM 变化添加效果。

(一)使用 transition 进行过渡

vue复制

复制代码
<template>
  <div>
    <button @click="show = !show">Toggle</button>
    <transition name="fade">
      <p v-if="show">Fade Transition</p>
    </transition>
  </div>
</template>

<style>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

(二)使用 animate.css 实现动画

vue复制

复制代码
<template>
  <div>
    <button @click="show = !show">Toggle</button>
    <transition name="bounce"
      enter-active-class="animate__animated animate__bounceIn"
      leave-active-class="animate__animated animate__bounceOut">
      <p v-if="show">Bounce Animation</p>
    </transition>
  </div>
</template>

九、Vue 的测试

(一)单元测试

Vue 提供了丰富的测试工具和框架,如 Jest 和 Vue Test Utils。

安装:

bash复制

复制代码
npm install --save-dev jest @vue/test-utils vue-jest

示例:

JavaScript复制

复制代码
// MyComponent.spec.js
import { shallowMount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

describe('MyComponent.vue', () => {
  it('renders a message', () => {
    const wrapper = shallowMount(MyComponent);
    expect(wrapper.text()).toContain('Hello World');
  });
});

(二)端到端测试

可以使用 Cypress 或 Nightwatch 等工具进行端到端测试。

安装 Cypress:

bash复制

复制代码
npm install cypress --save-dev

编写测试:

JavaScript复制

复制代码
describe('MyApp', () => {
  it('should display the title', () => {
    cy.visit('/');
    cy.contains('h1', 'Welcome to Vue.js');
  });
});

十、Vue 的优化

(一)代码分割

通过代码分割,可以将大文件拆分成多个小文件,按需加载,提高首屏加载速度。

JavaScript复制

复制代码
// 使用动态导入
const MyComponent = () => import('./MyComponent.vue');

(二)性能优化

  1. 避免不必要的渲染 :使用 v-oncev-memo

  2. 使用 keep-alive 缓存组件:减少组件的重复渲染。

  3. 优化数据绑定 :减少不必要的 watchcomputed

(三)SEO 优化

Vue 应用可以通过以下方式优化 SEO:

  1. 服务器端渲染(SSR):使用 Vue Server Renderer 渲染页面内容。

  2. 预渲染 :使用 prerender-spa-plugin 预渲染页面。

总结

Vue 是一个功能强大且灵活的前端框架,通过进阶学习,可以更好地掌握其核心特性,如响应式系统、生命周期、状态管理、路由、动画等。同时,了解如何优化 Vue 应用,进行单元测试和端到端测试,对于构建高效、可维护的现代 Web 应用至关重要。希望本文能够帮助你更好地理解和应用 Vue 的进阶知识。

相关推荐
不是吧这都有重名14 分钟前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹15 分钟前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
Maỿbe24 分钟前
利用html制作简历网页和求职信息网页
前端·html
森叶44 分钟前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹1 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹1 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts
繁依Fanyi1 小时前
ColorAid —— 一个面向设计师的色盲模拟工具开发记
开发语言·前端·vue.js·编辑器·codebuddy首席试玩官
codelxy1 小时前
vue引用cesium,解决“Not allowed to load local resource”报错
javascript·vue.js
程序猿阿伟2 小时前
《社交应用动态表情:RN与Flutter实战解码》
javascript·flutter·react native
明似水2 小时前
Flutter 开发入门:从一个简单的计数器应用开始
前端·javascript·flutter