面试总结(2024/10/16)
面试总结(2024/10/16)
- 面试1
- 1.闭包
- 2.promise
- 3.全局数据的保存
- 4.多模板切换,布局,系统主题颜色
- 5.同一个搜索,不同的搜索条件,输入框不同的校验方法
- 6.自定义一个组件,包括哪些属性
- 7.多个父组件之间传值
- 8.接口异常
- 9.Vue性能优化方法
- 面试2
- 1.遇到的难点,怎么解决的
- 2.首屏加载缓慢,怎么解决,从编码方面怎么解决,优化的角度
- 3.[vue MVVM 双向绑定(数据劫持+发布者-订阅者模式)](https://www.cnblogs.com/ceceliahappycoding/p/10604209.html)
- 4.vue相比jquery的优点是啥
- 5.v-if和v-show的区别,两个怎么选择
- 6.vue组件之间的传值
- 7.组件的类不想让其他的页面使用
- 8.防抖节流一般用的是什么
- 9.vue插槽
- 9.1 插槽的基本使用
- 9.2 默认插槽
- 9.3具名插槽
- 9.4template标签
- 9.5 作用域插槽
- 10.echarts怎么用的,接收数据的格式是什么
面试1
1.闭包
闭包是指在嵌套定义的函数中,一个内部函数引用了外部函数中的局部变量,并且外部函数返回了这个内部函数对象。闭包可以保存和访问它创建时的环境,即使在外部函数结束之后。
特点
- 访问内部变量:闭包可以访问其外部函数中的局部变量,即使外部函数已经执行完毕。
- 内存占用:闭包会占用一定的内存,因为局部变量不会被垃圾回收机制回收。
- 封装变量:闭包可以用于创建私有变量,封装内部实现细节。
- 保持状态:闭包可以保持某个状态,使函数记住之前的操作。
应用场景
- 封装变量:闭包可以用于创建私有变量,封装内部实现细节,避免全局变量的污染。
- 保存状态:闭包可以保持某个状态,使函数记住之前的操作。
- 函数工厂:闭包可以用于创建具有特定功能的函数,类似于工厂模式。
- 异步操作:闭包在异步编程中非常有用,可以保存上下文信息,避免回调地狱。
2.promise
3.全局数据的保存
用户信息
token
路由
数据保存有哪些方法
vuex
localstorage
sessionstorage
两者用法一致,相比于cookie,存储容量增加到了5M之多;区别点:
- localstorage是持久化存储,除非自己手动删除,关闭浏览器后依然存在;而sessionstorage关闭浏览器后自动删除。
- localstorage作用范围是整个浏览器,简单来说只要是用同一个浏览器打开的不同窗口还是不同网页之间都能够共享数据;而sessionstorage只能在同一个窗口下共享数据。
4.多模板切换,布局,系统主题颜色
切换怎么把颜色带过去
在Vue.js中更改系统颜色通常涉及CSS变量的使用。你可以在全局样式文件中定义CSS变量,并在组件中使用它们来实现颜色的动态更改。
在全局样式文件中定义CSS变量(例如main.css):
:root {
--primary-color: #3097d1; /* 默认主题颜色 */
--accent-color: #e91e63; /* 默认辅助色 */
}
在Vue组件中使用这些CSS变量:
<template>
<div :style="{ color: primaryColor }">
<!-- 内容 -->
</div>
</template>
<script>
export default {
data() {
return {
primaryColor: 'var(--primary-color)',
// 如果需要更改颜色,可以在这里设置新的值
// 例如: '#000000'
};
},
// 如果需要在运行时更改颜色,可以添加方法来更新primaryColor的值
methods: {
changeColor(newColor) {
this.primaryColor = newColor;
}
}
};
</script>
如果要在用户交互时更改颜色,可以添加事件监听器来触发changeColor方法:
<template>
<button @click="changeColor('#ff0000')">Change to Red</button>
</template>
每次调用changeColor方法时,它都会更新primaryColor的值,并且由于:style的绑定,使用这个变量的所有元素都会自动更新它们的颜色。
在 Vue 项目中全局切换系统的深色和浅色模式,你可以通过几种方式来实现。以下是一个设计思路,包括使用 CSS 变量、Vuex(或 Vue 的响应式数据)来管理主题状态,以及通过监听系统主题变化来自动切换主题。
步骤 1: 定义 CSS 变量
首先,在全局样式文件(如 App.vue 的 <style> 或单独的 CSS 文件中)定义一些 CSS 变量,这些变量将用于控制颜色主题。
css
:root {
--primary-color: #007bff;
--text-color: #000;
--background-color: #fff;
/* 其他颜色变量 */
}
[data-theme="dark"] {
--primary-color: #6c757d;
--text-color: #fff;
--background-color: #343a40;
/* 深色模式下的颜色变量 */
}
步骤 2: 使用 Vuex 管理主题状态(可选)
如果你的 Vue 项目使用了 Vuex,那么将主题状态存储在 Vuex store 中会是一个很好的选择。这样,你可以在任何组件中通过访问 store 来获取和设置主题。
javascript
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
darkMode: false, // 初始设置为浅色模式
},
mutations: {
toggleDarkMode(state) {
state.darkMode = !state.darkMode;
},
},
actions: {
// 如果需要,可以在这里添加异步操作
},
getters: {
isDarkMode: state => state.darkMode,
},
});
步骤 3: 监听系统主题变化并更新 Vuex 状态
在应用的入口文件(如 main.js 或 main.ts)中,监听系统的 prefers-color-scheme 媒体查询,并更新 Vuex store 中的主题状态。
javascript
// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';
// 监听系统主题变化
function updateTheme() {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
store.commit('toggleDarkMode', prefersDark);
}
updateTheme(); // 初始设置
// 监听媒体查询变化
window.matchMedia('(prefers-color-scheme: dark)').addListener(updateTheme);
new Vue({
store,
render: h => h(App),
}).$mount('#app');
注意:上面的 toggleDarkMode mutation 可能需要根据实际情况进行调整,因为直接将其设置为 prefersDark 可能会导致与用户手动切换主题时的行为不一致。你可能需要引入一个额外的状态或逻辑来区分系统主题和用户自定义主题。
步骤 4: 在 Vue 组件中应用主题
在你的 Vue 组件中,你可以通过绑定一个类名到根元素或使用计算属性来动态地应用主题。
vue
<template>
<div :class="{ 'dark-theme': isDarkMode }">
<!-- 组件内容 -->
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['isDarkMode']),
},
};
</script>
或者,如果你更喜欢不使用 Vuex,你也可以直接在根组件(如 App.vue)中监听系统主题变化,并通过 provide / inject 或 $emit / $on 机制将主题状态传递给子组件。
结论
通过结合 CSS 变量、Vuex(或 Vue 的响应式数据)以及媒体查询监听,你可以在 Vue 项目中轻松地实现全局的深色和浅色模式切换。这种方法的优点是易于维护和扩展,同时保持了代码的清晰和可重用性。
5.同一个搜索,不同的搜索条件,输入框不同的校验方法
6.自定义一个组件,包括哪些属性
在Vue中,可以通过创建一个单文件组件(.vue)来定义一个自定义组件。这个文件包括template、script和style标签。
以下是一个简单的自定义Vue组件的例子:
<template>
<div class="my-custom-component">
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<button @click="greet">Say Hi</button>
</div>
</template>
<script>
export default {
props: {
title: String,
message: String
},
methods: {
greet() {
alert('Hi!');
}
}
}
</script>
<style scoped>
.my-custom-component {
/* 组件样式 */
}
</style>
要使用这个组件,你需要先导入它,然后在父组件中注册并使用它。例如:
<template>
<div>
<my-custom-component title="Welcome" message="Hello there!" />
</div>
</template>
<script>
import MyCustomComponent from './components/MyCustomComponent.vue';
export default {
components: {
MyCustomComponent
}
}
</script>
在这个例子中,MyCustomComponent定义了两个属性title和message,以及一个方法greet。在父组件中,你可以通过属性传值的方式来设置这些属性,并且可以通过注册的标签名来使用这个组件。
7.多个父组件之间传值
在Vue中,多个父组件之间传值可以通过一个全局状态管理库(如Vuex)来实现,或者使用事件总线(Event Bus)模式。
8.接口异常
api返回异常
http请求的状态码异常
对应的api挂了
在Vue中,接口异常可能涉及以下几种情况:
- 网络问题:如无法连接到服务器,或请求超时。
- 服务器错误:服务器内部错误,如500等HTTP状态码。
- 数据处理错误:后端返回的数据格式不符合预期。
- 请求参数错误:向服务器发送了错误的请求参数。
解决方法:
- 网络问题:检查网络连接,设置合理的超时时间,使用try-catch处理网络请求。
- 服务器错误:在请求中添加错误处理,比如使用axios的.catch方法或者vue-resource的error回调。
- 数据处理错误:确保数据处理逻辑正确,检查后端返回的数据格式。
- 请求参数错误:验证请求参数的正确性,并提供用户反馈。
当出现错误时,需要在响应拦截提供异常提示
9.Vue性能优化方法
Vue 应用的性能优化可以从多个方面入手,以下是一些关键的性能优化方法:
-
使用v-if和v-show判断是否渲染元素,v-if为真时才渲染,v-show则总是渲染但可以通过CSS隐藏。
-
避免在列表渲染时使用v-if,因为它会导致渲染函数的重新构建。
-
使用计算属性或监听器来缓存计算结果,避免在模板中进行复杂的计算。
-
使用key属性来帮助Vue识别列表中各项的唯一性,优化列表渲染的过程。
-
避免在模板中进行复杂的表达式,可以将逻辑移到计算属性或方法中。
-
使用Webpack的terser-webpack-plugin插件和uglifyjs-webpack-plugin进行代码压缩和mangle。
-
使用路由懒加载来提升初始加载速度。
-
使用Vue的SSR(服务器端渲染)来提高非首屏页面的加载速度。
-
使用Vue Devtools进行性能分析,并遵循其提出的优化建议。
-
对于大型应用,考虑使用Vue的插件如Vuex和Vue Router的优化模式。
-
如果是大数据很长的列表,全部渲染的话一次性创建太多 DOM 就会非常卡,这时就可以用虚拟滚动,只渲染少部分(含可视区域)区域的内容,然后滚动的时候,不断替换可视区域的内容,模拟出滚动的效果
原理是监听滚动事件,动态更新需要显示的 DOM,并计算出在视图中的位移,这也意味着在滚动过程需要实时计算,有一定成本,所以如果数据量不是很大的情况下,用普通的滚动就行 -
v-for 遍历避免同时使用 v-if
为什么要避免同时使用 v-for 和 v-if
在 Vue2 中 v-for 优先级更高,所以编译过程中会把列表元素全部遍历生成虚拟 DOM,再来通过 v-if 判断符合条件的才渲染,就会造成性能的浪费,因为我们希望的是不符合条件的虚拟 DOM都不要生成
在 Vue3 中 v-if 的优先级更高,就意味着当判断条件是 v-for 遍历的列表中的属性的话,v-if 是拿不到的
- 第三方插件按需引入
比如 Element-UI 这样的第三方组件库可以按需引入避免体积太大,特别是项目不大的情况下,更没有必要完整引入组件库 - 路由懒加载
我们知道 Vue 是单页应用,所以如果没有用懒加载,就会导致进入首页时需要加载的内容过多,时间过长,就会出现长时间的白屏,很不利于用户体验,SEO 也不友好
所以可以去用懒加载将页面进行划分,需要的时候才加载对应的页面,以分担首页的加载压力,减少首页加载时间
- keep-alive缓存页面
比如在表单输入页面进入下一步后,再返回上一步到表单页时要保留表单输入的内容、比如在列表页>详情页>列表页,这样来回跳转的场景等
我们都可以通过内置组件 来把组件缓存起来,在组件切换的时候不进行卸载,这样当再次返回的时候,就能从缓存中快速渲染,而不是重新渲染,以节省性能
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</div>
</template>
也可以用 include/exclude 来 缓存/不缓存 指定组件
可通过两个生命周期 activated/deactivated 来获取当前组件状态
- 事件的销毁
Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件
而对于定时器、
addEventListener 注册的监听器等,就需要在组件销毁的生命周期钩子中手动销毁或解绑,以避免内存泄露
<script>
export default {
created() {
this.timer = setInterval(this.refresh, 2000)
addEventListener('touchmove', this.touchmove, false)
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
removeEventListener('touchmove', this.touchmove, false)
}
}
</script>
- 图片懒加载
图片懒加载就是对于有很多图片的页面,为了提高页面加载速度,只加载可视区域内的图片,可视区域外的等到滚动到可视区域后再去加载
Vue开发中的性能优化小技巧
面试2
1.遇到的难点,怎么解决的
2.首屏加载缓慢,怎么解决,从编码方面怎么解决,优化的角度
组件懒加载,路由懒加载
3.vue MVVM 双向绑定(数据劫持+发布者-订阅者模式)
4.vue相比jquery的优点是啥
-
简洁易学的MVVM架构:
Vue采用了简洁、易于理解的MVVM架构,这种架构使得开发者可以方便地进行视图和模型的分离,而无需处理复杂的DOM操作,特别是当我们需要处理的页面结构非常复杂时,这可以帮助我们简化代码的编写,提高代码的可维护性和可读性。 -
快速响应机制:
Vue采用了高性能的响应机制,这使得Vue可以更快地响应DOM的变化,并对数据进行更新。这样可以提供更好的用户体验,尤其在需要快速响应用户操作的场景中非常有用。 -
提供了丰富的生态系统:
Vue拥有丰富的生态系统,可以支持许多第三方组件和插件的使用。这使得开发者可以更轻松地实现各种功能和效果,从而提高开发效率,并且减少了重复造轮子的情况。 -
组件化开发的支持:
Vue支持组件化开发,开发者可以将复杂的页面结构分解为多个小的、可复用的组件,这样可以使代码更清晰、更易于维护。同时,Vue提供了多种使用过渡效果的方法,让页面切换变得更加平滑,增强用户体验。 -
强大的数据绑定功能:
Vue支持双向数据绑定,这意味着我们可以方便地将视图和模型进行绑定,并且当视图或模型发生变化时,对方也会自动更新,减少了DOM操作的次数,从而提高了性能。 -
与jQuery相比,Vue是一个轻量级的框架,
它的性能可能不如React或Angular,但它却提供了与React或Angular相似的功能和特性,这使得Vue成为了一个非常实用的前端框架,特别是对于那些需要管理数据和组件状态的项目。
1、精力集中。
Jq偏重于对dom的操作,由它的函数就很容易看出来,$()、parent()、find()。我们用jq的时候经常要去考虑怎么去渲染数据,怎么从视图中取到数据,操作数据前必须对dom节点进行选取修改赋值等操作,这其实分散了我们的本该放在业务逻辑上的精力。而Vue则是基于MVVM思想,数据驱动,双向绑定,只需要定义好渲染规则,如果数据发生改变,vue会帮我们重新渲染整个页面,所以我们只需将注意力放在数据操作上就可以了。
2、代码结构。
如果你用jq没有好的代码架构,很容易就回出现一种情况就是:js里写着html元素代码,而且可能会遍布很多地方。因为增删改查你都需要对dom进行操作,这里甚至可能会写多了些冗余代码。代码架构好一点的,可能会写成一种简版框架(即有专门的渲染函数,增删改查都会调用这个函数),依然是全域的,需要闭包。而vue就没有这个问题方法全部写在methods中,提供多种钩子函数对页面渲染过成进行精准操作。
3、操作性。
用jq去操作dom实际上是蛮麻烦的。比如说又个对象数组已经渲染成表格了,这时你需要修改某一个id的那个对象的数据行,jq的话最麻烦的做法就是在遍历里面先拿到id,检查相等,相等的话,用index去拿到要改的那个dom,再重新渲染。而用vue的话,可以直接修改数据就可以了,而且你甚至可以用Array.map Array.filter ,方便快捷,提升开发效率
4、模块化。
目前无论前端还是后端开发,越来越倾向于模块化组件化,以求降低不同模块,不同功能区块之间的耦合度,便于后期业务的修改与拓展,vue完全cover上述特性,而使用jq的时候,如果你的js牛逼轰轰的写得已经超长了,然后你又觉得需要分下模块了,这时你有两选择,1是用seajs,requirejs等,2是用原生的import去管理你的代码。说实话,我没怎么用过requirejs去分模块,可能是我压根就想没到这些js要怎么分。
5、单页面实现。
单页面的实现原理估计大家都很熟了,一般是几个div在来回切换。如果一开始已经写好html,再来回切的话,html是太长了。如果用js去写又拼的很麻烦。如果你想用jq、原生实现页面切换,我能想到比较好的方式是用模版引擎…吗?但其实单页面的实现我感觉没那么简单,你不单单要考虑html能否单独写出来,还要考虑js需不需要按需加载,路由需不需要等等。。。用vue就不需要烦这些东西,vue自动构建单页应用,使用router模拟跳转。
6、组件的复用。
用vue最爽的莫过于使用别人写好的组件。目前vue的生态已经非常庞大,主流的组件库有element-ui,iview,使用主流的组件库不仅避免了我们重复造轮子,而且方便新员工快速接手项目,某个大神的组件总结:https://www.toutiao.com/i6718405521088446988/?timestamp=1564450212&app=news_article&group_id=6718405521088446988&req_id=20190730093011010018026159736CF92,其实如果你项目大的时候,有些组件(一些功能和视图的集合)可能会复用。这些相对于jq就是插件了,个人不喜欢script引入插件(任性)
7、性能。
vue使用了虚拟dom技术,能够减少 dom的操作,能提高一定的效率。
5.v-if和v-show的区别,两个怎么选择
一、v-show与v-if相同点
视觉上来看,两者都控制DOM元素在页面上的显示
都是接受一个布尔值,当该值为true时,则显示该元素
当该值为false,不显示该元素,且不会占用页面位置(visibility: hidden会占据位置)
二、v-show与v-if区别
v-show本质上则是为该元素添加一个css–display:none,dom元素一直存在。
v-if本质则为真正意义上的条件渲染(销毁与创建dom元素),会触发组件的生命周期,因此频繁的使用会消耗性能。
三、延伸
如果涉及到频繁的切换 ,建议使用v-show
但是v-if同时还能搭配 v-else,v-else-if 会更加的灵活
如果有对组件重新渲染的需求,也可以考虑使用v-if
6.vue组件之间的传值
- 使用props传递数据:父组件可以通过属性的方式向子组件传递数据。
父组件:
<template>
<ChildComponent :parentData="data" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
data: '这是父组件的数据'
};
}
};
</script>
子组件:
<template>
<div>{{ parentData }}</div>
</template>
<script>
export default {
props: ['parentData']
};
</script>
- 使用 e m i t 发射事件:子组件可以使用 emit发射事件:子组件可以使用 emit发射事件:子组件可以使用emit方法触发一个事件,并传递数据给父组件。
子组件:
<template>
<button @click="sendToParent">发送数据给父组件</button>
</template>
<script>
export default {
methods: {
sendToParent() {
this.$emit('sendData', '这是子组件的数据');
}
}
};
</script>
父组件:
<template>
<ChildComponent @sendData="receiveData" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
receiveData(data) {
console.log(data); // 这是子组件的数据
}
}
};
</script>
- 使用Vuex管理状态:Vuex是一个专为Vue.js应用程序开发的状态管理模式。可以通过Vuex来集中管理组件间共享的状态。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
sharedData: '初始数据'
},
mutations: {
updateData(state, data) {
state.sharedData = data;
}
}
});
父组件:
<template>
<div>{{ $store.state.sharedData }}</div>
</template>
<script>
export default {
methods: {
updateSharedData() {
this.$store.commit('updateData', '新的数据');
}
}
};
</script>
子组件:
<template>
<button @click="updateSharedData">更新数据</button>
</template>
<script>
export default {
methods: {
updateSharedData() {
this.$store.commit('updateData', '子组件提供的新数据');
}
}
};
</script>
- 使用provide和inject:这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在该后代组件里面通过inject选项来接收。
父组件:
<template>
<ChildComponent />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
provide: {
sharedData: '这是父组件的数据'
},
components: {
ChildComponent
}
};
</script>
子组件:
<template>
<div>{{ sharedData }}</div>
</template>
<script>
export default {
inject: ['sharedData']
}
7.组件的类不想让其他的页面使用
scoped 在style
8.防抖节流一般用的是什么
一、防抖 (多次触发 只执行最后一次)
防抖策略(debounce)是当事件被触发后,延迟n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。
作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间。
- 防抖的应用场景
登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖文本编辑器实时保存,当无任何更改操作一秒后进行保存 - 防抖的实现思路、
// 防抖函数
function debounce(fn, wait) {
let timer;
return function() {
let _this = this;
let args = arguments;
if(timer) { clearTimeout(timer) }
timer = setTimeout(function(){
fn.apply(_this, args)
}, wait);
}
}
// 使用
window.onresize = debounce(function() {console.log('resize')}, 500)
<body>
<input type="text" id="inp">
<script>
// 1.封装防抖函数 **防抖重在清零 clearTimeout(timer)**
function debounce(fn, time) {
// 4.创建一个标记用来存放定时器的返回值
let timeout = null;
return function () {
// 5.每当用户触发input事件 把前一个 setTimeout 清楚掉
clearTimeout(timeout);
// 6.然后又创建一个新的 setTimeout, 这样就能保证输入字符后等待的间隔内 还有字符输入的话,就不会执行 setTimeout里面的内容
timeout = setTimeout(() => {
// 7.这里进行防抖的内容
fn();
}, time);
};
}
// 2.获取inpt元素
var inp = document.getElementById('inp');
// 8. 测试防抖临时使用的函数
function sayHi() {
console.log('防抖成功');
}
// 3.给inp绑定input事件 调用封装的防抖函数 传入要执行的内容与间隔事件
inp.addEventListener('input', debounce(sayHi, 5000));
</script>
</body>
二、节流 (规定时间内 只触发一次)
节流策略(throttle),控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。
作用: 高频率触发的事件,在指定的单位时间内,只响应第一次。
- 节流的应用场景
鼠标连续不断地触发某事件(如点击),单位时间内只触发一次;
监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断。例如:懒加载;
浏览器播放事件,每个一秒计算一次进度信息等 - 节流的实现思路
// 方式1: 使用时间戳
function throttle1(fn, wait) {
let time = 0;
return function() {
let _this = this;
let args = arguments;
let now = Date.now()
if(now - time > wait) {
fn.apply(_this, args);
time = now;
}
}
}
// 方式2: 使用定时器
function thorttle2(fn, wait) {
let timer;
return function () {
let _this = this;
let args = arguments;
if(!timer) {
timer = setTimeout(function(){
timer = null;
fn.apply(_this, args)
}, wait)
}
}
}
<script>
// 1.封装节流函数(使用定时器) 节流重在加锁 timer=timeout
function throttle(fn, time) {
//3. 通过闭包保存一个 "节流阀" 默认为false
let temp = false;
return function () {
//8.触发事件被调用 判断"节流阀" 是否为true 如果为true就直接trurn出去不做任何操作
if (temp) {
return;
} else {
//4. 如果节流阀为false 立即将节流阀设置为true
temp = true; //节流阀设置为true
//5. 开启定时器
setTimeout(() => {
//6. 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
//7. 最后在setTimeout执行完毕后再把标记'节流阀'为false(关键) 表示可以执行下一次循环了。当定时器没有执行的时候标记永远是true,在开头被return掉
temp = false;
}, time);
}
};
}
function sayHi(e) {
// 打印当前 document 的宽高
console.log(e.target.innerWidth, e.target.innerHeight);
}
// 2.绑定事件,绑定时就调用节流函数
// 敲黑板!!! 这里是重点 绑定是就要调用一下封装的节流函数 触发事件是触发封装函数内部的函数
window.addEventListener('resize', throttle(sayHi, 2000));
</script>
总结 (简要答案)
防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout。防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。业务场景有避免登录按钮多次点击的重复提交。
节流:控制流量,单位时间内事件只能触发一次,与服务器端的限流 (Rate Limit) 类似。代码实现重在开锁关锁 timer=timeout; timer=null。节流可以比作过红绿灯,每等一个红灯时间就可以过一批。
9.vue插槽
默认插槽,具名插槽,作用域插槽
9.1 插槽的基本使用
如下所示,一个父组件里面复用了子组件:
<template>
<div class="container">
<Student></Student>
<Student></Student>
<Student></Student>
</div>
</template>
student的结构也非常简单:
<template>
<div class="student">
<h3>巧克力小猫猿</h3></div>
</template>
插槽其实很简单,结合定义不难理解。我们可以在子组件中给父组件挖一个坑,父组件把内容放入子组件的坑中:
子组件中用slot标签挖坑
9.2 默认插槽
我们在使用插槽的时候,可以看出,给子组件挖了个slot的坑,父组件中通过子组件名的标签内部填坑的内容。
如果父组件中未指定内容,我们却需要一个默认值,该怎么办?
很简单,给插槽设置一个默认值即可:
<template>
<div class="student">
<!-- <slot></slot> -->
<h3>巧克力小猫猿</h3>
<slot>我是默认值</slot>
</div>
</template>
在父组件中只有第一个student的实例对象指定了插槽的内容,其他没有:
<template>
<div class="container">
<Student>加油</Student>
<Student></Student>
<Student></Student>
</div>
</template>
9.3具名插槽
给插槽和对应的内容模块带上相同的标记。让vue知道,把什么内容填充到什么插槽去。
在子组件中,给插槽取一个名字
<template>
<div class="student">
<slot name="up"></slot>
<h3>巧克力小猫猿</h3>
<slot name="job"></slot>
</div>
</template>
在父组件中,为内容指定需要放入的插槽名:
<template>
<div class="container">
<Student>
<h3 slot="up">加油</h3>
<h3 slot="job">找到工作</h3>
</Student>
<Student></Student>
<Student></Student>
</div>
</template>
9.4template标签
我们可以设置一个div,把所有的内容都装进去,这样就可以只写一个slot了:
<template>
<div class="container">
<Student>
<div slot="add">
<h3>加油</h3>
<div>找到工作</div>
</div>
</Student>
<Student></Student>
<Student></Student>
</div>
</template>
template标签的使用
把刚刚外部的div替换为template标签:
<template>
<div class="container">
<Student>
<template slot="add">
<h3>加油</h3>
<div>找到工作</div>
</template>
</Student>
<Student></Student>
<Student></Student>
</div>
</template>
结构上,并未多出什么多余结构,不生成真实DOM。
9.5 作用域插槽
作用域插槽的使用情景:当数据在组件自身,但根据数据生成的结构需要组件使用者来定,我们则可以使用作用域插槽。
<template>
<div class="student">
<slot :student="stus"></slot>
</div>
</template>
<script>
export default {
name: 'Student',
data() {
return {
stus: ['巧克力', '小猫', '猿']
}
}
}
</script>
<template>
<div class="container">
<Student>
<template scope="data">
{{ data }}
</template>
</Student>
</div>
</template>
<Student>
<template scope="data">
<ul>
<li v-for="s in data.student" :key="s.index">{{ s }}</li>
</ul>
</template>
</Student>
</div>
10.echarts怎么用的,接收数据的格式是什么
在开始之前,我们需要引入 ECharts 的 JavaScript 文件,并创建一个容器来展示图表。可以通过以下方式获取 ECharts:
<script src="https://cdn.jsdelivr.net/npm/echarts@5.1.1"></script>
然后,在 HTML 页面中创建一个
<div id="chart-container" style="width: 600px; height: 400px;"></div>
基本配置
创建一个基本的 ECharts 图表,需要先创建一个 echarts.init 实例,然后通过配置选项来定义图表的基本属性。
以下是一个简单的示例,演示如何创建一个柱状图:
// 创建图表实例
var chart = echarts.init(document.getElementById('chart-container'));
// 配置选项
var option = {
title: {
text: '柱状图示例'
},
xAxis: {
data: ['A', 'B', 'C', 'D', 'E']
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 15]
}]
};
// 使用配置选项设置图表
chart.setOption(option);
在上面的示例中,我们通过 echarts.init 方法创建了一个图表实例,并通过 document.getElementById 获取了图表容器的 DOM 元素。然后,我们定义了一个名为 option 的配置对象,其中包含了图表的标题、X 轴数据、Y 轴和数据系列。
最后,我们通过 chart.setOption 方法将配置选项应用到图表中,从而创建出一个柱状图。
配置选项
ECharts 的配置选项是一个包含各种属性和值的 JavaScript 对象,用于定义图表的各个方面,例如标题、轴线、图例、数据系列等。下面是一些常用的配置选项:
- title:图表的标题,包括主标题和副标题。
- legend:图例,用于展示数据系列的名称。
- xAxis 和 yAxis:X 轴和 Y 轴的配置,包括类型、标签、刻度等。
- grid:绘图区域的配置,包括位置、大小等。
- tooltip:鼠标悬停提示框的配置,用于展示数据详细信息。
- series:数据系列,用于定义要展示的数据和图表类型。
除了上述常用选项外,ECharts 还提供了众多其他选项,可以根据实际需求进行配置。