目录
七、vue打包,vue-cli打包,WebPack忽略指定文件或目录方式
一、父子组件数据双向数据绑定
父组件
父组件数据:{{riskQuarter}}
<div><component :is="checkedIt" :riskQuarter.sync='riskQuarter'></component></div>
import unitTable from "./unitTable.vue"; //下属单位
data(){
return{
checkedIt: "unitTable",
}
}
子组件
子传父<div @click="update">点击</div>
update(){
this.$emit('update:riskQuarter','子传父的值');
},
二、Vue 的独特优势
Vue 和其他前端框架相比,在结构、样式、业务分离等方面更清晰彻底,更符合前端多年来的编码习惯,更符合直觉、更容易学习和维护。
入门非常容易,资料丰富,框架功能完善,加入非常多的特性,例如,if, for, async,为开发者节省很多垃圾代码。模板支持 html 和 jsx,支持自定义指令,方便操作 dom 的一致行为。
一、门槛低、上手快Vue 上手简单的原因是无需复杂配置,只需要一个 HTML 与相关文件就能跑起来。从设计的角度上来看,Vue 考虑的也是如何降低门槛,让只掌握了 Web 基础知识 (HTML, CSS, JS) 的情况下,能够最快理解和上手,从而实现和完成一个应用。
二、人性化,符合用户习惯
React 的设计理念是提供强大而复杂的机制,让开发者来适应我;而 Vue 则是为了更适应开发者的使用习惯,在很多设定上都是让开发者怎么爽怎么来。
三、Vue + 第三方控件 = 效率高 & 使用便利 & 组件化架构
前面我们提到了 Vue 的两个基础特性,但能成为时代的发展趋势, 说明 Vue 的能力远不止于此。
从我们团队使用 Vue 的情况来看,Vue 使用起来异常简单,它从 React 那里借鉴了组件化、prop、单向数据流、性能、虚拟渲染,并意识到状态管理的重要性,并从 Angular 那里借鉴了模板,并赋予了更好的语法,以及双向数据绑定(在单个组件里),它不强制使用某种编译器,所以你完全可以在遗留代码里使用Vue,并对之前乱糟糟的jQuery代码进行改造。
三、什么是面向对象
在我们写代码中,所有操作都是通过对象,这就是面向对象,面向对象的思想,有封装,继承多态抽象。把一个具体的实物进行抽象化到程序里面,他就变成对象了。正所谓一切皆对象,所有实物到程序里面都会变成对象。每一个对象又代表着具体的事物。事物的数据像身高体重这种到了对象里面就变成了属性。而像跑与跳这种功能到了对象里面就叫做方法。
类就是对象的模型,根据类来创建对象。像是人的DNA决定着对象的结构和方法。
四、特别常见的问题——Vue 性能优化
(1)基础
-
非响应式数据通过 Object.freeze 冻结数据
-
嵌套层级不要过深
-
computed 和 watch 区别使用
-
v-if 和 v-show 区别使用
-
v-for 避免和 v-if 一起使用,且绑定 key 值要唯一
-
列表数据过多采用分页或者虚拟列表
-
组件销毁后清除定时器和事件
-
图片懒加载,图片压缩,启用GZIP压缩加速http传输速度,图片懒加载就是对于有很多图片的页面,为了提高页面加载速度,只加载可视区域内的图片,可视区域外的等到滚动到可视区域后再去加载
这个功能一些 UI 框架都有自带的,如果没有呢?
推荐一个第三方插件 vue-lazyload
npm i vue-lazyload -S // main.js import VueLazyload from 'vue-lazyload' Vue.use(VueLazyload) // 接着就可以在页面中使用 v-lazy 懒加载图片了 <img v-lazy="/static/images/1.png">
-
路由懒加载
-
防抖、节流
-
按需引入外部库、第三方插件按需引入
-
keep-alive缓存使用
-
服务端渲染(SSR——一般vue使用nuxt)和预渲染
14. webpack打包时分包——优化首屏加载
15. 使用v-show复用DOM
16.长列表性能优化——分页
17. 事件的销毁——监听后不需要了就及时销毁
18. 大量图标展示时使用精灵图(雪碧图)
19.组件化,对重复度高的功能进行封装
20.JSON是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。使用JSON格式来进行数据交换,
(2)详细
前端性能优化需要从前端的资源类型分析,以减少请求资源和请求时间为目的。目前的类型包括图片、javascript、css、动态数据等,不同的资源对于运算、带宽等的依赖也不同,因此优化的方式也不同。参照以往的经验和雅虎前端优化的策略,本系统分为以下方面:
1)根据浏览器加载数据的顺序不同,将加载的位置分为head内部和body之后
a,css尽可能的放到head内部
b,JavaScript放到body之后
a,合并不必要的单次后端请求;
b,首界面采用惰性加载,列表页采用分页加载;
c,javascript合并;
d,css合并
e,2k以内的请求采用get方式,反之采用post请求
3)通过数据压缩,减少数据传输的时间
a,服务器请求采用gzip压缩
b,banner图片采用图片压缩,压缩到200kb左右
c,javascript和css采用数据压缩
4)通过数据缓存增加请求的速度
a,图片资源,JavaScript、css 配置cdn
b,页面静态资源配置页面缓存;
5)多域名请求
a,将数据库、图片、应用程序等功能分开存储请求;
b,根据不同的业务划分不同的域名服务器
6)负载均衡
a,设定负载均衡,包括应用程序负载和数据库负载处理;
7)硬件配置提升
a,增加网络带宽
b,增加服务器处理能力
CSS优化
(1)将CSS代码放在HTML页面的顶部 (2)避免使用CSS表达式 (3)使用<link>来代替@import (4)避免使用Filters
以上的优化策略效果逐级提升,从成本的角度考虑,不同的阶段侧重点不同。优化的核心关键是理解问题的瓶颈,根据瓶颈和问题特点进行针对性优化。
路由懒加载
我们知道 Vue 是单页应用,所以如果没有用懒加载,就会导致进入首页时需要加载的内容过多,时间过长,就会出现长时间的白屏,很不利于用户体验,SEO 也不友好
所以可以去用懒加载将页面进行划分,需要的时候才加载对应的页面,以分担首页的加载压力,减少首页加载时间
没有用路由懒加载:
import Home from '@/components/Home' const router = new VueRouter({ routes: [ { path: '/home', component: Home } ] })
用了路由懒加载:
const router = new VueRouter({ routes: [ { path: '/home', component: () => import('@/components/Home') }, { path: '/login', component: require('@/components/Home').default } ] })
五、为什么说刷新页面vuex的数据会丢失
刷新页面vuex的数据会丢失属于正常现象,因为JS的数据都是保存在浏览器的堆栈内存里面的,刷新浏览器页面,以前堆栈申请的内存被释放,这就是浏览器的运行机制,那么堆栈里的数据自然就清空了。
- vuex存储的数据只是在页面中,相当于全局变量,页面刷新时vuex里的数据会重新初始化,导致数据丢失
- vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据会被重新赋值
六、ui框架开发时候的难点
1.全局样式覆盖
2.在ui组件基础上进行二次开发
七、vue打包,vue-cli打包,WebPack忽略指定文件或目录方式
webpack.base.conf.js文件的
module: {
rules: []
}
加入
{
test: /\H5$/,
loader: 'url-loader',
options: {
// limit: 10,
generator: (content, mimetype, encoding, resourcePath) => {
return ''
}
},
},
打包的时候成功忽略H5文件夹,H5是另一个项目
八、测试开发工程师是干啥的
这个职位需要会后端语言,一般是JAVA,不要求掌握多牛,会点前端更好,初级水平就行,然后会测试,业务测试、性能测试各种,一般是开发一些测试工具供普通测试人员使用或给领导演示流程用,所以要求会编写自动化测试脚本,接口自动化等,做这些主要是方便后期回归测试,而且减少了失误,减少了没必要的工作交接、熟悉业务的时间,编写测试工具文档并且根据新需求去维护,这就是测试开发工程师。
例如:web端使用selenium+testng+maven+jenkins的框架来进行二次开发脚本
app端的话使用appium+testng+maven+jenkins
九、ES6的class类的用法
class infoDisposeFn{
//构造方法,放函数内部可调用的变量
constructor(num,repeatNum){
this.num=num;
this.repeatNum=repeatNum;
}
//方法
repeatNow(methods='floor'){
if(methods=='floor')
return Math.floor( this.num*this.repeatNum);
if(methods=='round')return Math.round( this.num*this.repeatNum);
}
}
const newInfoDisposeFn=new infoDisposeFn(6.6,3);
const floorNum=newInfoDisposeFn.repeatNow('floor'),roundNum=newInfoDisposeFn.repeatNow('round');
console.log('floorOver===>',floorNum,'round====>',roundNum);
输出:
floorOver===> 19 round====> 20
下面咱们来玩一下class的继承——extends
class extendsTestFn extends infoDisposeFn{
constructor(userName){
this.userName=userName;
}
sayMyName(){
console.log(this.userName||'海森堡')
}
}
const getTestInfo=new extendsTestFn('怀特');
getTestInfo.sayMyName();
发现报错
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
继承的正确用法如下,用到了super去继承变量
class extendsTestFn extends infoDisposeFn{
constructor(num,repeatNum,userName){
super(num,repeatNum);//继承父级构造方法内容
this.userName=userName;
}
sayMyName(){
super.repeatNow()//可以继承父构造函数的方法
console.log(this.userName||'海森堡',this.repeatNow())
}
}
const getTestInfo=new extendsTestFn(7.7,5,'怀特');
getTestInfo.sayMyName();
console.log(getTestInfo.repeatNum);
输出:
怀特 5
但说真的这玩意在搞vue开发的人这儿一般用不到。
十、关于常见问题:你有没有在开发中碰到过什么难点?
遇到难点,你的思考,如何提出问题,如何跟他人协作解决,跨组沟通等等
业务上的难点 也不在技术实现上。而在于理解业务上。
技术上的难点 不在于技术上,而在于怎么用技术解决业务问题
我的理解是,面试官会遍历所有人这个问题。我们回答这个问题的目标是,比其他人回答的都好是最好了。
如果是我,所以可以刻意设计一个难点:比如:项目性能优化,团队开发效率插件或者工具,CICD模块等等。
描述思路:遇到什么样的问题,带来什么影响。有哪些解决问题的思路,技术方案选型,最终定论是哪个。
然后去网上扒一个好的故事,自己也能够hold住的。我个人感觉就可以加分。
如果我是面试官。我看你解决问题的维度是什么,还有就是解决问题的思路是什么。所以维度最好高一些,思路能够讲好就行了
十一、Vue3监听滚动事件
let oldScrollTop: number = 0; // 记录上一次滚动结束后的滚动距离
const scrollTop = ref<number>(0); // 记录当前的滚动距离
const scrollFixedStatus = ref<boolean>(true);
function handleScroll() {
window.addEventListener('scroll', () => {
scrollTop.value = window.scrollY;
});
}
onMounted(() => {
handleScroll();
});
onBeforeUnmount(() => {
window.removeEventListener('scroll', () => {}); // 离开当前组件别忘记移除事件监听
});
watch(
() => scrollTop.value,
(newValue, oldValue) => {
setTimeout(() => {
if (newValue === window.scrollY) {
// 延时执行后当newValue等于window.scrollY,代表滚动结束
// console.log('滚动结束');
oldScrollTop = newValue; // 每次滚动结束后都要给oldScrollTop赋值
// scrollFixedStatus.value = true;
}
}, 20); // 必须使用延时器,否则每次newValue和window.scrollY都相等,无法判断,20ms刚好大于watch的侦听周期,故延时20ms
if (oldScrollTop === oldValue) {
scrollFixedStatus.value = false;
// 每次滚动开始时oldScrollTop与oldValue相等
// console.log('滚动开始');
}
}
);