当前位置: 首页 > news >正文

vue前端面试

一 .v-if和v-show的区别

v-ifv-show 是 Vue.js 中两个常用的条件渲染指令,它们都可以根据条件决定是否渲染某个元素。但是它们之间存在一些区别。

  1. 语法:v-ifv-show 的语法相同,都接收一个布尔值作为参数。
<div v-if="show">Hello, World!</div>
<div v-show="show">Hello, World!</div>
  1. 条件渲染:v-if 会根据条件决定是否渲染整个元素,如果条件为 false,则元素不会被渲染;v-show 会根据条件决定是否显示元素,如果条件为 false,则元素会隐藏,但仍然存在于 DOM 中。
<div v-if="show">Hello, World!</div>
<div v-show="show">Hello, World!</div>
  1. 性能:v-if 会根据条件决定是否渲染整个元素,如果条件为 false,则元素不会被渲染,这种情况下,Vue.js 会销毁和重建元素,性能较差;v-show 会根据条件决定是否显示元素,如果条件为 false,则元素会隐藏,但仍然存在于 DOM 中,这种情况下,Vue.js 不会销毁和重建元素,性能较好。

总结:v-ifv-show 都可以根据条件决定是否渲染某个元素,但它们之间存在一些区别。v-if 会根据条件决定是否渲染整个元素,如果条件为 false,则元素不会被渲染,这种情况下,Vue.js 会销毁和重建元素,性能较差;v-show 会根据条件决定是否显示元素,如果条件为 false,则元素会隐藏,但仍然存在于 DOM 中,这种情况下,Vue.js 不会销毁和重建元素,性能较好。在实际使用中,可以根据具体需求选择合适的指令。

二.如何理解mvvm

MVVM(Model-View-ViewModel)是一种前端开发模式,它将数据与视图分离,从而提高代码的可维护性和可扩展性。

在 MVVM 模式中,Model 表示数据模型,View 表示视图,ViewModel 表示视图模型。数据模型负责存储数据,视图负责展示数据,视图模型负责将数据与视图进行绑定。

在 MVVM 模式中,视图模型负责将数据与视图进行绑定。当数据模型中的数据发生变化时,视图模型会自动更新视图,从而实现数据与视图的双向绑定。

以下是一个简单的 MVVM 示例:

<template><div><input v-model="searchText" placeholder="Search" /><p>Search text: {{ searchText }}</p></div>
</template><script>
export default {data() {return {searchText: ''};}
};
</script>

在这个示例中,searchText 是数据模型,<input><p> 是视图,v-model 是视图模型。当用户在输入框中输入内容时,searchText 会自动更新,视图中的内容也会自动更新。

总结:MVVM 是一种前端开发模式,它将数据与视图分离,从而提高代码的可维护性和可扩展性。在 MVVM 模式中,视图模型负责将数据与视图进行绑定,实现数据与视图的双向绑定。

model-view-viewmodel的缩写,是一种设计思想。

model就是数据模型,用于定义数据修改和操作。

view是视图。

viewmodel是连接view和model的桥梁。

当数据改变时,viewmodel通过监听到数据变化,自动更新视图,当用户操作视图时,viewmodel可以监听视图变化,通知数据进行改动。

viewmodel通过双向绑定把view和model连接起来,他们之间的同步是自动的。

三.组件生命周期

Vue 组件的生命周期指的是组件从创建到销毁的一系列过程,可以分为创建、挂载、更新、销毁四个阶段。

  1. 创建阶段:在创建阶段,Vue 会进行一些初始化工作,如初始化数据、事件、计算属性等。

  2. 挂载阶段:在挂载阶段,Vue 会根据模板编译生成 DOM,并将数据与 DOM 进行绑定。

  3. 更新阶段:在更新阶段,Vue 会根据数据的变化,更新 DOM。

  4. 销毁阶段:在销毁阶段,Vue 会进行一些清理工作,如解绑事件、计算属性等。

以下是 Vue 组件的生命周期钩子函数:

  1. beforeCreate:在创建阶段之前调用,此时 Vue 实例尚未被创建。

  2. created:在创建阶段之后调用,此时 Vue 实例已经被创建,但 DOM 尚未被编译。

  3. beforeMount:在挂载阶段之前调用,此时 DOM 尚未被编译。

  4. mounted:在挂载阶段之后调用,此时 DOM 已经被编译,但尚未被渲染。

  5. beforeUpdate:在更新阶段之前调用,此时 DOM 已经被渲染,但数据尚未被更新。

  6. updated:在更新阶段之后调用,此时 DOM 已经被更新,但尚未被渲染。

  7. beforeUnmount:在销毁阶段之前调用,此时 DOM 已经被渲染,但尚未被解绑。

  8. unmounted:在销毁阶段之后调用,此时 DOM 已经被解绑,Vue 实例已被销毁。

总结:Vue 组件的生命周期指的是组件从创建到销毁的一系列过程,可以分为创建、挂载、更新、销毁四个阶段。在不同的生命周期阶段,Vue 会调用不同的生命周期钩子函数,我们可以通过这些钩子函数来执行一些特定的操作。

简言之:

  1. 创建

beforeCreate:属性和方法都不能使用

created:实例创建完成之后,可以使用和修改数据,但页面没有被渲染

  1. 挂载

beforemount:虚拟dom创建完成,即将渲染

mounted:把编译好的模板挂载到页面

  1. 更新

beforeUpdate:组件更新之前使用,数据是新的,页面上的数据是旧的,组件即将更新

updated:render重新渲染,数据和页面都是新的

  1. 销毁

beforeDestory:清除定时器等操作

destroyed:组件被销毁

使用keep-alive时多出两个

activited:组件激活时

deactivited:组件销毁时

四.在created和mounted去请求数据,有什么区别

在 Vue.js 中,createdmounted 是两个常用的生命周期钩子函数,都可以用来请求数据。但是它们之间存在一些区别。

  1. 调用时间:created 钩子函数在 Vue 实例被创建后立即调用,此时 Vue 实例的 datamethods 属性已经初始化,但 DOM 尚未被编译;mounted 钩子函数在 DOM 被编译后调用,此时 Vue 实例的 datamethods 属性已经初始化,DOM 已经渲染。

  2. 请求数据:在 created 钩子函数中请求数据,如果请求失败,可能会导致 Vue 实例无法被创建;在 mounted 钩子函数中请求数据,即使请求失败,也不会影响 Vue 实例的创建和渲染。

  3. 页面加载速度:在 created 钩子函数中请求数据,可能会导致页面加载速度变慢,因为请求数据需要时间;在 mounted 钩子函数中请求数据,可以确保在页面加载完成后立即请求数据,从而提高页面加载速度。

总结:createdmounted 都可以用来请求数据,但它们之间存在一些区别。created 钩子函数在 Vue 实例被创建后立即调用,此时 Vue 实例的 datamethods 属性已经初始化,但 DOM 尚未被编译;mounted 钩子函数在 DOM 被编译后调用,此时 Vue 实例的 datamethods 属性已经初始化,DOM 已经渲染。在实际使用中,可以根据具体需求选择合适的钩子函数来请求数据。

created:渲染前调用,先初始化数据。

mounted:渲染后调用,请求数据可能会出现闪屏,created不会。

请求的数据对dom有影响,使用created,与dom无关,可以放在mounted。

五.vue组件通信

Vue 组件通信主要有以下几种方式:

  1. props 和 $emit:通过 props,父组件可以将数据传递给子组件;通过 $emit,子组件可以将数据传递给父组件。
<!-- 父组件 -->
<template><div><child-component :message="parentMessage"></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {parentMessage: 'Hello from parent'};}
};
</script>
<!-- 子组件 -->
<template><div>{{ message }}<button @click="sendMessage">Send message to parent</button></div>
</template><script>
export default {props: ['message'],methods: {sendMessage() {this.$emit('message-sent', 'Hello from child');}}
};
</script>
  1. .sync 修饰符:在 Vue 2.3.0 版本中,引入了 .sync 修饰符,可以简化子组件修改父组件数据的操作。
<!-- 父组件 -->
<template><div><child-component :message.sync="parentMessage"></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {parentMessage: 'Hello from parent'};}
};
</script>
<!-- 子组件 -->
<template><div>{{ message }}<button @click="sendMessage">Send message to parent</button></div>
</template><script>
export default {props: ['message'],methods: {sendMessage() {this.message = 'Hello from child';this.$emit('update:message', 'Hello from child');}}
};
</script>
  1. Vuex:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式与库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);export default new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}},modules: {count: {state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}}}}
});
  1. $root 和 $parent:通过 $root 和 $parent,可以访问到 Vue 实例的根节点和父节点。
<!-- 子组件 -->
<template><div>{{ rootMessage }}{{ parentMessage }}</div>
</template><script>
export default {inject: ['rootMessage', 'parentMessage'],created() {console.log(this.$root); // 访问根节点console.log(this.$parent); // 访问父节点}
};
</script>

总结:Vue 组件通信主要有 props$emit.sync 修饰符、Vuex、$root 和 $parent 等方式。在实际项目中,可以根据具体需求选择合适的通信方式。

简言之:

父传子:props,$ref --引用信息对象会注册在父组件$refs对象上

子传父:$emit—子组件绑定自定义事件,子组件绑定接收

兄弟传:全局事件总线$buson和emit来进行数据传输

六.keep-alive

keep-alive 是 Vue.js 提供的一个生命周期钩子函数,它会在组件被销毁后,将其缓存到内存中,当再次访问时,会从缓存中取出组件实例,而不是重新创建一个新的实例。这样可以减少内存的消耗,提高页面的加载速度。

keep-alive 主要用于需要频繁切换的页面,如首页、列表页等。当用户在两个页面之间频繁切换时,使用 keep-alive 可以避免频繁地创建和销毁组件实例,从而提高页面的加载速度。

要使用 keep-alive,需要遵循以下步骤:

  1. 在需要缓存的组件上添加 keep-alive 属性。
<template><div><!-- 页面内容 --></div>
</template><script>
export default {name: 'MyComponent',keepAlive: true
};
</script>
  1. keep-alive 生命周期钩子函数中,可以进行一些缓存数据的处理。
export default {name: 'MyComponent',keepAlive: true,mounted() {console.log('Component mounted');},destroyed() {console.log('Component destroyed');}
};

注意:keep-alive 主要用于需要频繁切换的页面,对于一些需要根据用户操作进行缓存的数据,可以使用 Vuex 等状态管理库进行管理。

是vue的内置组件,包裹组件时,会缓存不活跃的组件实例。

防止重复渲染、减少加载时间和性能消耗。

七. axios如何封装

Axios 是一个基于 Promise 的 HTTP 客户端,用于在浏览器和 Node.js 中发起 HTTP 请求。 Axios 具有以下特点:

  1. 支持 Promise API
  2. 支持拦截器
  3. 支持请求和响应的数据处理
  4. 支持取消请求
  5. 支持自动转换 JSON

下面是一个简单的 Axios 封装示例:

  1. 安装 Axios:
npm install axios
  1. 创建 axios.js 文件,封装 Axios:
import axios from 'axios';const instance = axios.create({// 基本 URLbaseURL: 'https://api.example.com',timeout: 5000,
});// 请求拦截器
instance.interceptors.request.use(function (config) {// 在发送请求之前做些什么return config;},function (error) {// 对请求错误做些什么return Promise.reject(error);}
);// 响应拦截器
instance.interceptors.response.use(function (response) {// 对响应数据做点什么return response;},function (error) {// 对响应错误做点什么return Promise.reject(error);}
);export default instance;
  1. 在需要使用 Axios 的地方引入封装好的 Axios:
import axios from './axios';axios.get('/users').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});

在这个示例中,我们创建了一个名为 instance 的 Axios 实例,并设置了请求拦截器和响应拦截器。然后,我们将封装好的 Axios 实例导出,以便在其他地方使用。

注意:这个示例仅作为参考,实际项目中可能需要根据具体需求进行调整。

下载axios----创建实例----封装请求和响应拦截器----封装接口-----使用

八.vue路由传参

Vue.js 中的路由传参主要有以下几种方式:

  1. 使用 query 参数:在路由的路径中添加 query 参数,如 /search?keyword=xxx。在组件中,可以通过 this.$route.query 获取 query 参数。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,props: true}
];const router = new VueRouter({routes
});export default router;
<!-- Search.vue -->
<template><div><h2>Search</h2><p>Keyword: {{ keyword }}</p></div>
</template><script>
export default {props: ['keyword']
};
</script>
  1. 使用 props:在路由的 props 属性中定义需要传递的参数,如 { keyword: String }。在组件中,可以通过 this.$route.params 获取 params 参数。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search/:keyword',name: 'Search',component: Search,props: {keyword: String}}
];const router = new VueRouter({routes
});export default router;
<!-- Search.vue -->
<template><div><h2>Search</h2><p>Keyword: {{ keyword }}</p></div>
</template><script>
export default {props: ['keyword']
};
</script>
  1. 使用 to 属性:在路由的 to 属性中,可以使用 { propName: propValue } 的形式传递参数。在组件中,可以通过 this.$route.params 获取 params 参数。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,to: {name: 'Search',params: {keyword: 'xxx'}}}
];const router = new VueRouter({routes
});export default router;
<!-- Search.vue -->
<template><div><h2>Search</h2><p>Keyword: {{ keyword }}</p></div>
</template><script>
export default {props: ['keyword']
};
</script>

总结:Vue.js 中的路由传参主要有使用 query 参数、使用 props 和使用 to 属性三种方式。在实际项目中,可以根据具体需求选择合适的传参方式。

params传参:this.$router.push({name:'',params:{}})

this.$route.params.id

路由属性传参

this.$router.push({name:'/${item.id}'})

路由配置{path:'/index:id'}

query传参

this.$router.push({name:'index',query:{}})

九.路由hash模式和history有啥区别

路由的 hash 模式和 history 模式的主要区别在于 URL 的表现形式和浏览器的历史记录。

  1. URL 表现形式:
  • hash 模式:URL 中会带有 # 符号,如 http://example.com/#/search
  • history 模式:URL 中不会带有 # 符号,如 http://example.com/search
  1. 浏览器历史记录:
  • hash 模式:在浏览器中,点击回退按钮会返回到上一个页面,而不是跳转到上一个 URL。
  • history 模式:在浏览器中,点击回退按钮会跳转到上一个 URL,而不是返回到上一个页面。

总结:hash 模式和 history 模式的主要区别在于 URL 的表现形式和浏览器的历史记录。在实际项目中,可以根据具体需求选择合适的路由模式。

  1. hash地址上有#,history没有

  2. 地址栏回车刷新时,hash会加载相应页面,history会报404

  3. hash支持低版本浏览器,因为H5新增的API

  4. hash不会重新加载页面

  5. history有历史记录,可以通过pushState和replaceState(0)去修改历史记录,并不立刻发送请求

  6. history需要后台配置

十.路由拦截

Vue.js 中的路由拦截主要通过导航守卫来实现。导航守卫是 Vue Router 提供的全局导航守卫,可以在路由导航过程中执行一些操作,如拦截导航、改变导航参数等。

Vue Router 提供了以下几种导航守卫:

  1. beforeEach:在导航守卫中,可以在导航到新路由之前执行一些操作。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,beforeEach: (to, from, next) => {// 在这里可以执行一些操作,如验证用户是否登录if (!userLoggedIn) {next({ name: 'Login' });} else {next();}}}
];const router = new VueRouter({routes
});export default router;
  1. beforeEnter:在导航守卫中,可以在导航到新路由之前执行一些操作。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,beforeEnter: (to, from, next) => {// 在这里可以执行一些操作,如验证用户是否登录if (!userLoggedIn) {next({ name: 'Login' });} else {next();}}}
];const router = new VueRouter({routes
});export default router;
  1. beforeRouteEnter:在导航守卫中,可以在导航到新路由之前执行一些操作。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,beforeRouteEnter: (to, from, next) => {// 在这里可以执行一些操作,如验证用户是否登录if (!userLoggedIn) {next({ name: 'Login' });} else {next();}}}
];const router = new VueRouter({routes
});export default router;
  1. beforeRouteUpdate:在导航守卫中,可以在导航到新路由之前执行一些操作。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,beforeRouteUpdate: (to, from, next) => {// 在这里可以执行一些操作,如验证用户是否登录if (!userLoggedIn) {next({ name: 'Login' });} else {next();}}}
];const router = new VueRouter({routes
});export default router;
  1. beforeRouteLeave:在导航守卫中,可以在导航离开当前路由之前执行一些操作。
// router.js
import VueRouter from 'vue-router';
import Search from './components/Search.vue';const routes = [{path: '/search',name: 'Search',component: Search,beforeRouteLeave: (to, from, next) => {// 在这里可以执行一些操作,如保存当前路由信息saveCurrentRouteInfo();next();}}
];const router = new VueRouter({routes
});export default router;

总结:Vue.js 中的路由拦截主要通过导航守卫来实现。导航守卫是 Vue Router 提供的全局导航守卫,可以在路由导航过程中执行一些操作,如拦截导航、改变导航参数等。在实际项目中,可以根据具体需求使用导航守卫来实现

router.before e ach((to,from,next)=>{})

十一.vue的动态路由

在路由配置里设置meta属性,扩展权限相关字段,在路由导航守卫里判断这个权限标识实现动态的增加和跳转路由

十二…如何解决刷新后二次加载路由

window.location.reload()matchercosnt router=createRouter()export function resetRouter(){const newRouter=creatRouter()router.matcher=newRouter.matcher}

十三.vuex刷新页面数据丢失

vuex会重新获取数据

把数据保存在浏览器缓存里cookie、localstorage、session

页面刷新时,再次请求数据,动态更新vuex里面的数据

十四.computed和watch区别

computedwatch 是 Vue.js 中两个重要的属性,它们都可以实现数据的双向绑定,但它们之间存在一些区别。

  1. 定义方式:computed 是通过 Object.defineProperty() 方法来定义的,而 watch 是通过 Vue.prototype.watch 方法来定义的。

  2. 依赖收集:computed 属性会进行依赖收集,当依赖的数据发生变化时,会自动更新视图;而 watch 属性不会进行依赖收集,需要手动触发视图更新。

  3. 缓存:computed 属性会缓存计算结果,当依赖数据发生变化时,会重新计算;而 watch 属性不会缓存计算结果,每次都会重新计算。

  4. 性能:computed 属性性能比 watch 属性高,因为它进行了依赖收集,而 watch 属性需要手动触发视图更新。

总结:computedwatch 都可以实现数据的双向绑定,但它们之间存在一些区别。computed 属性会进行依赖收集,当依赖的数据发生变化时,会自动更新视图;而 watch 属性不会进行依赖收集,需要手动触发视图更新。computed 属性会缓存计算结果,当依赖数据发生变化时,会重新计算;而 watch 属性不会缓存计算结果,每次都会重新计算。computed 属性性能比 watch 属性高,因为它进行了依赖收集。

  1. computed:计算属性,支持缓存,以来的属性值发生变化,计算属性会重新计算,否则用缓存,不支持异步,第一次加载就监听,函数中必须有return

  2. watch:监听属性,监听data中数据的变化,不支持缓存,支持异步,第一次加载不监听,可以不用有return

十五.vuex使用场景和属性

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 适用于需要共享状态的应用程序。

Vuex 具有以下属性:

  1. 状态(state):Vuex 通过 state 属性来定义应用程序的状态。状态可以是嵌套的对象,也可以是基本的数据类型。

  2. 突变(mutations):Vuex 通过 mutations 属性来定义状态的突变。突变是同步的,并且只能通过 commit 方法来触发。

  3. 操作(actions):Vuex 通过 actions 属性来定义异步操作。操作可以触发突变,也可以执行其他异步操作。

  4. 模块(modules):Vuex 通过 modules 属性来定义模块。模块可以包含自己的状态、突变、操作和模块。

Vuex 适用于以下场景:

  1. 单页面应用程序:Vuex 适用于需要共享状态的单页面应用程序。

  2. 多组件应用程序:Vuex 适用于需要共享状态的多组件应用程序。

  3. 需要状态持久化的应用程序:Vuex 适用于需要状态持久化的应用程序。

  4. 需要权限控制的应用程序:Vuex 适用于需要权限控制的应用程序。

使用 Vuex 的步骤:

  1. 安装 Vuex:

    使用 npm 或 yarn 安装 Vuex:

    npm install vuex --save
    

    yarn add vuex
    
  2. 创建 Vuex store:

    在项目中创建一个名为 store.js 的文件,并在其中创建一个 Vuex store:

    import Vue from 'vue';
    import Vuex from 'vuex';Vue.use(Vuex);export default new Vuex.Store({state: {},mutations: {},actions: {},modules: {}
    });
    
  3. 定义状态、突变、操作和模块:

    store.js 文件中,可以定义状态、突变、操作和模块。例如:

    state: {count: 0
    },
    mutations: {increment(state) {state.count++;}
    },
    actions: {increment(context) {context.commit('increment');}
    },
    modules: {count: {state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}}}
    }
    
  4. 引入 store 到 main.js:

    main.js 文件中,引入 store.js 并将其添加到 Vue 实例中:

    import Vue from 'vue';
    import App from './App.vue';
    import store from './store';new Vue({store,render: h => h(App)
    }).$mount('#app');
    
  5. 使用 mapState、mapGetters、mapMutations 和 mapActions:

    在 Vue 组件中,可以使用 mapStatemapGettersmapMutationsmapActions 辅助函数来简化代码。例如:

    import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';export default {computed: {...mapState(['count'])},methods: {...mapMutations(['increment']),...mapActions(['increment'])}
    };
    

总结:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 适用于需要共享状态的应用程序,如单页面应用程序、多组件应用程序

state:存储变量

getters:state的计算属性

mutations:提交更新数据的方法,同步

actions:异步操作

modules:模块化vuex

用户个人信息、购物车等

十六.vue双向绑定的原理

Vue.js 中的双向绑定是通过 Object.defineProperty() 方法实现的。这个方法可以让我们在访问或修改一个属性时执行一些自定义操作。Vue.js 利用这个方法实现了数据的双向绑定。

具体来说,Vue.js 会将数据对象中的每个属性转换为 getter 和 setter,从而实现数据的双向绑定。当数据对象中的属性被访问或修改时,getter 和 setter 会被触发,从而更新视图。

以下是一个简单的示例:

class Vue {constructor(data) {this.data = data;for (const key in data) {Object.defineProperty(this, key, {get() {return this.data[key];},set(value) {this.data[key] = value;}});}}
}const vm = new Vue({data: {count: 0}
});console.log(vm.count); // 输出 0
vm.count = 1;
console.log(vm.count); // 输出 1

在这个示例中,我们创建了一个简单的 Vue 类,它将数据对象中的每个属性转换为 getter 和 setter。当我们访问或修改 vm.count 时,getter 和 setter 会被触发,从而更新视图。

Vue.js 利用这个原理实现了数据的双向绑定,从而实现数据和视图的同步。

通过数据劫持结合发布者订阅者模式,利用object.defineProperty()劫持各个属性的setter和getter,在数据发生变化时发布消息给订阅者,触发相应的监听回调渲染视图。

十七.diff和虚拟dom

diff 和虚拟 DOM 是前端性能优化的重要技术。diff 算法用于计算新旧 DOM 之间的差异,从而实现最小化页面重排和重绘。虚拟 DOM 是一种模拟 DOM 的技术,它将实际 DOM 转换为虚拟 DOM,然后在虚拟 DOM 上进行操作,最后将虚拟 DOM 转换回实际 DOM。

diff 算法的核心思想是将新旧 DOM 进行比较,找出它们之间的差异,然后将差异应用到实际 DOM 上。diff 算法的实现方式有很多,如深度优先搜索(DFS)、广度优先搜索(BFS)等。

虚拟 DOM 的实现方式是将实际 DOM 转换为虚拟 DOM,然后将虚拟 DOM 存储在内存中。当需要更新 DOM 时,先将新的虚拟 DOM 转换回实际 DOM,然后将新 DOM 与旧 DOM 进行比较,找出差异,最后将差异应用到实际 DOM 上。

以下是一个简单的示例:

// 假设这是实际 DOM
const oldDom = document.createElement('div');
oldDom.innerHTML = '<p>Hello, World!</p>';// 创建虚拟 DOM
const vdom = {type: 'div',props: {},children: [{type: 'p',props: {},children: ['Hello, World!']}]
};// 将虚拟 DOM 转换回实际 DOM
const newDom = createElement(vdom);// 比较新旧 DOM,找出差异
const patches = diff(oldDom, newDom);// 将差异应用到实际 DOM 上
applyPatches(oldDom, patches);

在这个示例中,我们首先创建了一个实际 DOM 和一个虚拟 DOM。然后,我们将虚拟 DOM 转换回实际 DOM,并比较新旧 DOM,找出差异。最后,我们将差异应用到实际 DOM 上。

通过使用 diff 和虚拟 DOM,我们可以实现前端性能优化,减少页面重排和重绘。

虚拟dom,描述元素与元素之间的关系,创建的一个js对象。

如果组件内有响应的数据,数据发生改变时,render函数会生成一个新的虚拟dom,新的虚拟dom会和旧的虚拟dom进行比对,找到需要修改的虚拟dom内容,然后去对应的真实dom中修改。

diff是虚拟dom对比时用的,返回一个patch对象来存储两个节点不同的地方,最后用patch里的记录信息更新真实dom。

十八.vue和jquery的区别

Vue.js 和 jQuery 都是前端流行的 JavaScript 库,但它们之间存在一些关键区别。

  1. 核心思想:Vue.js 的核心思想是数据绑定和视图渲染,而 jQuery 的核心思想是选择器、操作 DOM 和事件处理。

  2. 语法:Vue.js 使用基于 HTML 的模板语法,而 jQuery 使用基于 CSS 的选择器语法。

  3. 数据绑定:Vue.js 支持数据双向绑定,而 jQuery 不支持。

  4. 视图渲染:Vue.js 支持组件化和响应式视图,而 jQuery 不支持。

  5. 性能:Vue.js 的性能通常比 jQuery 更高,因为它使用了虚拟 DOM 和优化了 DOM 操作。

  6. 社区支持:Vue.js 拥有庞大的社区支持,而 jQuery 的社区支持正在逐渐减少。

  7. 兼容性:Vue.js 支持现代浏览器,而 jQuery 支持旧版浏览器。

总结:Vue.js 和 jQuery 都是前端流行的 JavaScript 库,但它们之间存在一些关键区别。Vue.js 更注重数据绑定和视图渲染,而 jQuery 更注重选择器、操作 DOM 和事件处理。在性能、社区支持和兼容性等方面,Vue.js 通常比 jQuery 更具优势。

  1. 原理不同:vue就是数据绑定,jq时先获取dom在处理。

  2. 着重点不同:vue是数据驱动,jq着重于页面。

  3. 操作不同

十九.vuex的响应式处理

触发事件的时候会通过dispatch来访问action中的方法,actions中的commit会触发mutations中的方法从而修改state里的值,通过getter把数据更新到视图。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式与库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 能够实现响应式处理,主要依赖于它的响应式系统。

Vuex 的响应式系统依赖于 Vue.js 的响应式系统。Vue.js 通过 Object.defineProperty() 方法实现响应式,当访问或修改一个响应式对象的属性时,会自动触发视图更新。Vuex 利用这一点,将 store 中的状态通过 getters 暴露给组件,使得组件可以访问和修改这些状态。

当组件修改 store 中的状态时,Vuex 会自动触发视图更新,从而实现响应式处理。这种机制使得组件之间的状态可以保持同步,避免了传统方式下组件之间的状态不同步的问题。

下面是一个简单的 Vuex 响应式处理示例:

  1. 首先,安装 Vuex:
npm install vuex --save
  1. 创建一个 Vuex store:
// store.js
import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);export default new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}},modules: {count: {state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}}}},getters: {count(state) {return state.count;}}
});
  1. 在 main.js 中引入 store,并将其添加到 Vue 实例中:
// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';Vue.config.productionTip = false;new Vue({store,render: h => h(App)
}).$mount('#app');
  1. 在组件中使用 mapGetters 和 mapActions 获取 store 中的状态和操作:
// App.vue
import { mapGetters, mapActions } from 'vuex';export default {computed: {...mapGetters(['count'])},methods: {...mapActions(['increment'])},created() {this.increment();}
};

在这个示例中,我们创建了一个简单的 Vuex store,并在组件中使用 mapGetters 和 mapActions 获取 store 中的状态和操作。当组件修改 store 中的状态时,Vuex 会自动触发视图更新,从而实现响应式处理。

二十.如何封装组件

使用Vue.extend()创建一个组件

使用Vue.components()方法注册组件
封装组件是一种提高代码复用性和可维护性的有效方法。在 Vue 中,封装组件通常包括以下步骤:

  1. 创建基础组件:首先,创建一个基础组件,该组件包含通用的属性和方法。
// BaseComponent.vue
<template><div><h2>{{ title }}</h2><p>{{ content }}</p></div>
</template><script>
export default {props: {title: String,content: String}
};
</script>
  1. 创建子组件:然后,创建多个子组件,这些子组件继承自基础组件,并添加或重写属性和方法。
// ChildComponent1.vue
<template><BaseComponent title="Title1" content="Content1" />
</template><script>
import BaseComponent from './BaseComponent.vue';export default {components: {BaseComponent}
};
</script>
// ChildComponent2.vue
<template><BaseComponent title="Title2" content="Content2" />
</template><script>
import BaseComponent from './BaseComponent.vue';export default {components: {BaseComponent}
};
</script>
  1. 使用子组件:最后,在需要使用这些子组件的地方,可以直接使用它们。
// ParentComponent.vue
<template><div><ChildComponent1 /><ChildComponent2 /></div>
</template><script>
import ChildComponent1 from './ChildComponent1.vue';
import ChildComponent2 from './ChildComponent2.vue';export default {components: {ChildComponent1,ChildComponent2}
};
</script>

通过这种方式,我们可以将通用的代码封装到基础组件中,并在子组件中添加或重写特定的属性和方法。这样,当我们需要修改或扩展这些组件时,只需在基础组件或子组件中进行修改,其他引用这些组件的地方会自动同步更新。

此外,我们还可以使用 Vue 的插槽(slots)功能来进一步封装组件。插槽允许我们在父组件中插入子组件的内容,从而使子组件更加灵活和可扩展。

// BaseComponentWithSlots.vue
<template><div><h2>{{ title }}</h2><slot></slot></div>
</template><script>
export default {props: {title: String}
};
</script>
// ChildComponentWithSlots.vue
<template><BaseComponentWithSlots title="Title"><p>{{ content }}</p></BaseComponentWithSlots>
</template><script>
import BaseComponentWithSlots from './BaseComponentWithSlots.vue';export default {components: {BaseComponentWithSlots},props: {content: String}
};
</script>

在这个示例中,我们创建了一个带有插槽的基础组件,并在子组件中使用插槽插入自定义内容。这样,子组件可以更加灵活地继承和扩展基础组件。

二十二.vue过滤器

插值表达式、v-bind可以使用过滤器

全局:Vue.filter

局部:和methods同级,filter

在 Vue.js 中,过滤器(filter)是一种用于格式化数据的方法。过滤器可以接收一个或多个参数,并返回一个格式化后的值。在 Vue.js 2.x 中,过滤器是一个全局对象,可以在任何组件中使用。但在 Vue.js 3.x 中,过滤器已被移除,取而代之的是计算属性(computed)和函数方法(methods)。

下面是一个简单的过滤器示例:

  1. 创建一个过滤器:
// 定义一个名为 `formatDate` 的过滤器
Vue.filter('formatDate', function (value, format) {if (!value) return '';return new Date(value).toLocaleString(format);
});

在这个示例中,我们创建了一个名为 formatDate 的过滤器,它接收两个参数:valueformatvalue 是需要格式化的日期值,format 是日期格式。过滤器使用 toLocaleString 方法将日期格式化为指定格式的字符串。

  1. 在组件中使用过滤器:
<template><div><p>原始日期:{{ date }}</p><p>格式化后的日期:{{ date | formatDate('en-US', 'long') }}</p></div>
</template><script>
export default {data() {return {date: new Date()};}
};
</script>

在这个示例中,我们在组件的模板中使用了 formatDate 过滤器。| 符号用于将过滤器应用到 date 数据上。过滤器的第一个参数是过滤器名称,第二个参数是过滤器参数,这里分别是日期格式和语言环境。

注意,在 Vue.js 3.x 中,过滤器已被移除,取而代之的是计算属性(computed)和函数方法(methods)。计算属性可以实现类似过滤器的功能,但计算属性只能用于组件的 data 中,不能全局使用。

// 使用计算属性实现过滤器
export default {data() {return {date: new Date()};},computed: {formattedDate() {return new Date(this.date).toLocaleString('en-US', 'long');}}
};

在这个示例中,我们使用计算属性 formattedDate 实现了类似过滤器的功能。计算属性会自动缓存计算结果,只有当 date 数据发生变化时才会重新计算。

二十三.vue中强制刷新

localtion.reliad()

this.$router.go(0)

provide和inject

location.reload() 是 JavaScript 中的一个方法,用于重新加载当前页面的所有内容。这个方法会清除页面上的所有缓存,并从服务器重新获取页面内容。

在 Vue.js 中,如果你想要强制刷新当前页面,可以使用 this.$router.replace() 方法。这个方法会清除当前路由的缓存,并重新导航到当前路由。

下面是一个简单的示例:

this.$router.replace({name: this.$route.name,params: this.$route.params,query: this.$route.query
});

在这个示例中,我们使用 this.$router.replace() 方法清除当前路由的缓存,并重新导航到当前路由。这将强制刷新当前页面,并从服务器重新获取页面内容。

请注意,this.$router.replace() 方法会清除当前路由的缓存,但不会清除其他路由的缓存。如果你想要清除所有路由的缓存,可以使用 this.$router.replace() 方法,并传递一个空对象作为参数。

this.$router.replace({});

this.$router.go(0) 是 Vue.js 中的一个方法,用于导航到指定路由。参数 0 表示当前路由,所以 this.$router.go(0) 相当于重新加载当前页面。

当你想要强制刷新当前页面时,可以使用 this.$router.go(0)。这将清除当前路由的缓存,并重新导航到当前路由,从而强制刷新当前页面。

下面是一个简单的示例:

this.$router.go(0);

在这个示例中,我们使用 this.$router.go(0) 强制刷新当前页面。

请注意,this.$router.go(0) 会清除当前路由的缓存,但不会清除其他路由的缓存。如果你想要清除所有路由的缓存,可以使用 this.$router.replace() 方法,并传递一个空对象作为参数。

this.$router.replace({});

provideinject 是 Vue.js 提供的一种依赖注入的方式。它们主要用于在组件之间共享数据,而不必显式地传递它们。当使用 provideinject 时,如果提供的数据发生变化,注入的组件会自动更新。

但是,如果你想要强制刷新使用 provideinject 的组件,可以使用以下方法:

  1. 在提供者组件中,使用 this.$forceUpdate() 方法强制刷新组件。
// 提供者组件
export default {provide() {return {message: 'Hello, Vue!'};},methods: {changeMessage() {this.message = 'Hello, world!';this.$forceUpdate(); // 强制刷新组件}}
};
  1. 在注入者组件中,使用 this.$forceUpdate() 方法强制刷新组件。
// 注入者组件
export default {inject: ['message'],mounted() {console.log(this.message); // 输出: Hello, Vue!this.message = 'Hello, world!';this.$forceUpdate(); // 强制刷新组件console.log(this.message); // 输出: Hello, world!}
};

在这个示例中,提供者组件使用 provide 方法提供 message 数据,并在 changeMessage 方法中修改 message 数据并强制刷新组件。注入者组件使用 inject 方法注入 message 数据,并在 mounted 生命周期钩子中修改 message 数据并强制刷新组件。

请注意,this.$forceUpdate() 方法应该被谨慎使用,因为它会强制组件重新渲染,可能会导致不必要的性能损失。在大多数情况下,你应该尽量避免使用这个方法,而是应该使用 Vue 的响应式系统来更新数据。

二十三.vue2和vue3的区别

Vue.js 是一个流行的前端框架,用于构建单页面应用程序。Vue.js 2 和 Vue.js 3 是 Vue.js 的两个主要版本。下面是它们的一些主要区别:

  1. 性能:Vue.js 3 的性能比 Vue.js 2 有所提升。Vue.js 3 使用 Proxy 代替 Object.defineProperty,这使得 Vue.js 3 的性能更接近原生 React。

  2. 响应式系统:Vue.js 3 使用新的响应式系统,称为 Vue 3 Reactive。这个系统使用 reactiveref 函数创建响应式对象和变量,而不是使用 data 属性。Vue.js 3 的响应式系统比 Vue.js 2 的响应式系统更简洁和易用。

  3. Composition API:Vue.js 3 引入了 Composition API,它允许你更灵活地组织和管理代码。Composition API 是 Vue.js 3 的主要功能之一,它允许你创建可重用的组件逻辑,例如状态管理、响应式数据、生命周期钩子等。

  4. 新的特性:Vue.js 3 还引入了一些新的特性,例如 setup 函数、onMountedonUnmounted 生命周期钩子、自定义渲染器等。

总的来说,Vue.js 3 在性能、响应式系统、Composition API 等方面都比 Vue.js 2 更强大和易用。如果你正在考虑使用 Vue.js,建议使用 Vue.js 3,因为它代表了 Vue.js 的最新技术和最佳实践。

如果你正在使用 Vue.js 2,并且不想升级到 Vue.js 3,那么你可以继续使用 Vue.js 2,并享受它的稳定性和社区支持。但是,请注意,Vue.js 2 已经不再更新,所以如果你需要最新的功能和性能,建议升级到 Vue.js 3。

  1. 双向数据绑定原理不同:vue2使用defindpropty(),vue3使用proxy

  2. 支持碎片

  3. API不同

  4. 定义数据变量方法不同,vue3—setup

  5. 生命周期不同

  6. 传值不同

  7. 指令和插槽不同

  8. main.js不同

二十四.vue性能优化

Vue.js 性能优化可以从多个方面进行,下面是一些常见的方法:

  1. 使用响应式数据:Vue.js 使用响应式数据来跟踪数据变化并自动更新视图。确保只将需要追踪的数据设置为响应式,避免将整个对象或数组都设置为响应式,这可能会导致性能问题。

  2. 使用计算属性:计算属性是基于它们的依赖进行缓存的,只有在依赖发生改变时才会重新计算它们的值。避免在模板中直接使用复杂表达式,可以将计算属性用于处理数据并将其暴露给模板。

  3. 使用方法:方法可以让你在数据变化时执行一些额外的操作,例如更新其他数据或调用 API。避免在模板中直接使用方法,可以将它们移到 methods 对象中。

  4. 使用生命周期钩子:生命周期钩子可以在组件的不同阶段执行一些操作,例如创建、更新、销毁等。避免在生命周期钩子中执行不必要的操作,可以将它们移到生命周期钩子之外。

  5. 使用指令:指令可以让你在 DOM 元素上添加一些额外的操作,例如事件监听、属性绑定等。避免在模板中直接使用指令,可以将它们移到 v-on 或 v-bind 属性中。

  6. 使用插件:插件可以让你在 Vue.js 应用程序中添加一些额外的功能,例如状态管理、路由等。避免使用过多的插件,以免增加应用程序的复杂性和性能负担。

  7. 使用优化工具:有一些工具可以帮助你找到 Vue.js 应用程序中的性能瓶颈,例如 Vue.js 官方提供的性能分析工具 vue-perf。使用这些工具可以让你更好地了解应用程序的性能,并找到需要优化的地方。

下面是一个简单的示例,展示如何在 Vue.js 中使用响应式数据、计算属性和方法:

<template><div><p>原始数据:{{ message }}</p><p>反转后的数据:{{ reversedMessage }}</p><button @click="changeMessage">修改数据</button></div>
</template><script>
export default {data() {return {message: 'Hello Vue!'};},computed: {reversedMessage() {return this.message.split('').reverse().join('');}},methods: {changeMessage() {this.message = 'Hello, Vue!';}}
};
</script>

在这个示例中,我们使用响应式数据 message,计算属性 reversedMessage 和方法 changeMessage 来处理数据并更新视图。这样可以避免在模板中直接使用复杂表达式和指令,从而提高性能。

不要把所有数据都放在data中

v-for给每个元素绑定事件用事件代理

keep-alive缓存组件

尽可能差分组件,提高复用性

key要保持唯一

合理使用路由懒加载

数据持久化存储尽量用防抖、节流优化

按需加载、内容懒加载、图片懒加载

骨架屏

seo优化:预渲染、服务端渲染ssr

cdn形式引入第三方模块、多线程打包、抽离公共文件

客户端缓存、服务端缓存、服务端Gzip压缩

二十五.首屏优化

首屏优化是指优化网页首次加载时的性能,使得用户能够更快地看到网页的主要内容。下面是一些常见的首屏优化方法:

  1. 使用 SSR(服务器端渲染):SSR 可以将部分或全部页面内容在服务器端渲染,然后将渲染好的内容发送到客户端。这样,用户在客户端收到数据后可以直接看到首屏内容,而不是等待客户端渲染。

  2. 使用 CDN:使用 CDN 可以加速静态资源的加载速度。将静态资源(如 CSS、JavaScript、图片等)托管在 CDN 服务器上,这样用户在访问网页时可以直接从 CDN 服务器获取资源,而不是从源服务器获取。

  3. 优化静态资源:优化静态资源可以减小它们的体积,从而加快加载速度。例如,可以使用压缩工具压缩 CSS 和 JavaScript 文件,使用图片压缩工具压缩图片等。

  4. 使用动态加载:对于一些较大的静态资源,可以使用动态加载的方式,即在需要时才加载资源,而不是一次性加载所有资源。这样可以避免在加载首屏时加载不必要的资源,从而提高加载速度。

  5. 减少 HTTP 请求:减少 HTTP 请求可以加快网页的加载速度。可以使用 HTTP 缓存来避免重复请求相同的资源,可以使用合并请求来减少请求次数等。

  6. 优化首屏加载时间:可以使用一些工具(如 Google PageSpeed Insights、WebPageTest 等)来分析网页的首屏加载时间,找出瓶颈并优化它们。

下面是一个简单的示例,展示如何使用 SSR 和 CDN 进行首屏优化:

// SSR
export default {mounted() {const app = this.$createApp(App);app.mount('#app');}
};// CDN
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" />
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js"></script>

在这个示例中,我们使用 SSR 在服务器端渲染 App 组件,然后将渲染好的内容发送到客户端。同时,我们使用 CDN 托管 CSS、JavaScript 和图片等静态资源,以便用户在访问网页时可以直接从 CDN 服务器获取资源,从而加快首屏加载速度。

使用路由懒加载

非首屏组件使用异步

首屏不重要的组件延迟加载

动态资源放在cdn

减少首屏js、css等资源文件大小

使用服务端渲染

减少dom数量和层级

使用精灵图请求

做一些liading

开启Gzip

图片懒加载

二十六.vue为什么使用proxy

proxy可以代理整个对象

代理对象的监听方法更丰富

代理对象会生成一个新的对象,不会修改对象本身

不兼容ie浏览器

Vue.js 使用 Proxy 对象来跟踪对象的变化并自动更新视图。Proxy 对象可以拦截对对象的读取和设置操作,从而在对象发生变化时触发视图更新。

使用 Proxy 对象的好处是,它可以更准确地跟踪对象的变化,并且可以避免使用 Object.defineProperty 的一些限制和问题。例如,Object.defineProperty 无法处理数组和对象嵌套的情况,而 Proxy 对象可以。

下面是一个简单的示例,展示 Vue.js 如何使用 Proxy 对象:

import { reactive, toRefs } from 'vue';const state = reactive({count: 0,user: {name: 'John',age: 30}
});const stateRefs = toRefs(state);console.log(stateRefs.count); // 0
console.log(stateRefs.user.name); // 'John'stateRefs.count++;
console.log(stateRefs.count); // 1
console.log(stateRefs.user.name); // 'John'stateRefs.user.name = 'Jane';
console.log(stateRefs.user.name); // 'Jane'

在这个示例中,我们使用 reactive 函数创建了一个响应式对象 state,然后使用 toRefs 函数将响应式对象转换为具有响应式属性的普通对象 stateRefs。当我们修改 stateRefs 对象的属性时,Vue.js 会自动更新视图。

注意,虽然 Proxy 对象可以更准确地跟踪对象的变化,但在某些情况下,它们可能比 Object.defineProperty 更慢。因此,Vue.js 会在性能和准确性之间进行权衡,根据情况选择使用 Proxy 对象或 Object.defineProperty。

二十七.seo如何优化

SEO(搜索引擎优化)是一种优化网站以提高网站在搜索引擎结果页面(SERP)中排名的方法。对于 Vue.js 应用程序,SEO 优化可以通过以下方法进行:

  1. 使用服务器端渲染(SSR):SSR 可以将部分或全部页面内容在服务器端渲染,然后将渲染好的内容发送到客户端。这样,搜索引擎可以更容易地抓取和索引你的网页内容。可以使用 Vue.js 的官方 SSR 库 vue-ssr 进行 SSR。

  2. 优化静态资源:优化静态资源可以减小它们的体积,从而加快网页的加载速度。这可以提高搜索引擎抓取和索引网页内容的速度。可以使用压缩工具压缩 CSS、JavaScript 和图片等静态资源。

  3. 使用动态加载:对于一些较大的静态资源,可以使用动态加载的方式,即在需要时才加载资源,而不是一次性加载所有资源。这样可以避免在加载首屏时加载不必要的资源,从而提高加载速度。

  4. 减少 HTTP 请求:减少 HTTP 请求可以加快网页的加载速度。可以使用 HTTP 缓存来避免重复请求相同的资源,可以使用合并请求来减少请求次数等。

  5. 优化网页结构:优化网页结构可以提高搜索引擎抓取和索引网页内容的效率。可以使用 semantic HTML 标签、添加 <meta> 标签、优化网站导航等方法进行网页结构优化。

  6. 创建搜索引擎友好的 URL:搜索引擎友好的 URL 可以提高搜索引擎抓取和索引网页内容的效率。可以使用简洁、清晰、易于理解的 URL,避免使用动态 URL 和复杂的参数。

  7. 添加搜索引擎优化工具:可以使用一些搜索引擎优化工具,如 Google Search Console、Mozilla SEO Toolbar 等,来分析网页的 SEO 性能,找出瓶颈并优化它们。

下面是一个简单的示例,展示如何使用 SSR 和静态资源优化进行 SEO 优化:

// SSR
export default {mounted() {const app = this.$createApp(App);app.mount('#app');}
};// 静态资源优化
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" />
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js"></script>

在这个示例中,我们使用 SSR 在服务器端渲染 App 组件,然后将渲染好的内容发送到客户端。同时,我们使用 CDN 托管 CSS、JavaScript 和图片等静态资源,以便用户在访问网页时可以直接从 CDN 服务器获取资源,从而加快网页加载速度。

注意,虽然 SEO 优化可以提高搜索引擎抓取和索引网页内容的效率,但不要过度优化。搜索引擎可能会惩罚过度优化的网站,降低它们的排名。始终遵循搜索引擎优化最佳实践,为用户提供有价值的内容。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 数据建设实践之大数据平台(四)
  • 搜索引擎算法工程师,在query理解方面,都有哪些方面的工作
  • 水库大坝安全监测险情应对措施
  • vscode使用ssh连接远程服务器
  • 【Java数据结构】初识线性表之一:顺序表
  • 基于springboot+mybatis学生管理系统
  • vivado EQUIVALENT_DRIVER_OPT、EXCLUDE_PLACEMENT
  • OS_同步与互斥
  • Xcode15报错: SDK does not contain ‘libarclite‘
  • Python 给存入 Redis 的键值对设置过期时间
  • 红酒与城市探索:品味都市的多元风情
  • 初学SpringMVC之接收请求参数及数据回显
  • 神经网络和安全结合:一种基于神经网络的智能攻击检测与防御系统;构建攻击行为预测模型
  • SD卡讲解
  • 347. 前 K 个高频元素(中等)
  • hexo+github搭建个人博客
  • SegmentFault for Android 3.0 发布
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 2017届校招提前批面试回顾
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • flask接收请求并推入栈
  • golang 发送GET和POST示例
  • HashMap ConcurrentHashMap
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • Java教程_软件开发基础
  • JS基础之数据类型、对象、原型、原型链、继承
  • Laravel核心解读--Facades
  • Selenium实战教程系列(二)---元素定位
  • 对象引论
  • 通过npm或yarn自动生成vue组件
  • 学习Vue.js的五个小例子
  • 一个JAVA程序员成长之路分享
  • 原生js练习题---第五课
  • 正则与JS中的正则
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​批处理文件中的errorlevel用法
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (1)Nginx简介和安装教程
  • (19)夹钳(用于送货)
  • (30)数组元素和与数字和的绝对差
  • (C)一些题4
  • (poj1.2.1)1970(筛选法模拟)
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (第61天)多租户架构(CDB/PDB)
  • (接口封装)
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)事件系统
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)Google的Objective-C编码规范
  • (转)JAVA中的堆栈
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .bat批处理(五):遍历指定目录下资源文件并更新