前言
日志,各位看官就当乐子看吧。
正经人谁写日记啊?!!
----鹅城县长
今天看了vue的知识,但不算系统复习,直接进入彩蛋环节。
彩蛋
实施的面试可能没机会了,凉了。所以下午在招聘软件上和HR对线。有一个外包公司回复了,发了一个笔试题。于是下午刷了一下题目,想临时抱佛脚。牛客上面的字符串的三道题,一起来看看吧。
字符串编程题
NC89 字符串变形
对于一个长度为 n 字符串,我们需要对它做一些变形。
首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。
比如"Hello World"变形后就变成了"wORLD hELLO"。
function trans(s, n){
//write code here
// 参考用时最短的代码发现:
// 1. 提前对字符串再拼接是没有必要的
// 2. 大小写字母的转化可以简化为:
// tmpArr[j]==tmpArr[j].toLowerCase()?tmpArr[j].toUpperCase():tmpArr[j].toLowerCase()
let revStr=s.split(' ').reverse().join(' ');
let tmpArr=revStr.split('')
for(let i=0;i<n;i++){
let letter=tmpArr[i]
if(letter!==' ' && letter>='a' && letter<="z"){
tmpArr[i]=letter.toUpperCase()
}else if(letter!==' ' && letter>='A' && letter<="Z"){
tmpArr[i]=letter.toLowerCase()
}
}
return tmpArr.join('');
}
module.exports = {
trans : trans
}
NC55 最长公共前缀
给你一个大小为 n 的字符串数组 strs ,其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀,返回这个公共前缀。
/**
*
* @param strs string字符串一维数组
* @return string字符串
*/
function longestCommonPrefix( strs ) {
// write code here
// 参考他人代码发现:
// 1.排序起初是考虑对数值型字符串,按字典顺序排会造成 112排在2前面。但是题目只是为了找最长前缀,不需要将短字符串排在长字符串前面。
// 2.基于以上,找最长前缀的逻辑也可以简化,直接取第一和最后一个元素,找他们的公共前缀就可以了
strs.sort((a,b)=>{
if(a.length>b.length) return true;
else if(a.length===b.length) return a>b;
else return false;
})
let first=strs[0]?strs[0]:'';
let i=first.length;
while(i>0){
let subStr=first.slice(0,i);
let isMatch=strs.every((value)=>{
// 前缀,符合则返回0
return value.indexOf(subStr)===0
})
if(isMatch) break;
i--;
}
return first.slice(0,i);
}
module.exports = {
longestCommonPrefix : longestCommonPrefix
};x : longestCommonPrefix
};
NC113 验证IP地址
编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址
IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(“.”)分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。
IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (“:”)分割。比如, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。
然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (:😃 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。
说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。
/**
* 验证IP地址
* @param IP string字符串 一个IP地址字符串
* @return string字符串
*/
function solve( IP ) {
// write code here
// 参考他人代码,并没有很特别的地方,所以这个就不分析了。感觉牛客上的题解比较正常,LeetCode上大神好多
let res=''
if(IP.includes('.') && !IP.includes(':')){
// . ipv4的分割符
let arr=IP.split('.')
for(let value of arr){
if(!(value) || isNaN(value) || (value!=0 && value.indexOf(0)===0) || (value>255) || (value<0)){
res="Neither";
break;
}
}
return res||'IPv4';
}else if(IP.includes(':') && !IP.includes('.')){
// : ipv6的分割符
let arr=IP.split(':')
for(let value of arr){
let vArr=value.split('');
// 空,或超出4位长度
if ((!value) || (vArr.length>4)){
res='Neither'
break;
}
// 不是16进制的数值
// 存在非16进制就返回 Neither
vArr.some((el)=>{
el=el.toUpperCase()
if(isNaN(el) && (el>'F' || el<'A') ){
res='Neither'
return true;
}
})
}
return res||'IPv6';
}else{
return "Neither"
}
}
module.exports = {
solve : solve
};
其他
Vue
vue的学习还是逃不过了解vue2.0啊!!!难受哦
说说vue
前端开发框架,核心特性是数据驱动型,即MVVM模型,M(model)就是业务逻辑块,负责交互;V(view)视图层,即页面,最终的效果;VM(viewmodel)视图模块层,用来连接M和V,数据更新后,最终如何从M更新到V就是这层在负责。和传统开发相比:vue基本不直接操作DOM;和react相比:不同在于react使用单向数据流;diff逻辑不同,react及时更新到虚拟DOM上,然后批量更新到DOM中,vue边对比边更新。
vue生命周期
v2和v3的简单对照
周期 | 描述 | 和v3区别(销毁过程改名) | v3中对应的钩子函数 |
---|---|---|---|
beforeCreate | 使用组合式api,直接用setup代替 | ||
created | 组件的数据和事件已经被初始化,可以被调用 | setup | |
beforeMount | 编译模板但是没有渲染 | 其余单词前+on | |
mounted | DOM初始化完成,可以进行操作 | ||
beforeUpdate | data数据已经是最新了 | ||
updated | 页面和data都是最新的数据 | ||
beforeDestroy | data和method等等还可以访问 | beforeUnmount | |
destroyed | 组件销毁,内部数据不可用 | unmounted |
new vue()的过程
拿源码一通分析,不是很理解,记得一个UP主说的,就做两件事儿:初始化和创建数据更新机制。
说说SPA
单页面程序,网页程序的模型,通过动态重写实现页面的变化。基于对url的监听API的实现,看看大佬写的代码。
hash模式
// 定义 Router
class Router {
constructor () {
this.routes = {}; // 存放路由path及callback
this.currentUrl = '';
// 监听路由change调用相对应的路由回调
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
this.routes[path] && this.routes[path]()
}
}
// 使用 router
window.miniRouter = new Router();
miniRouter.route('/', () => console.log('page1'))
miniRouter.route('/page2', () => console.log('page2'))
miniRouter.push('/') // page1
miniRouter.push('/page2') // page2
history模式,这个不大懂
// 定义 Router
class Router {
constructor () {
this.routes = {};
this.listerPopState()
}
init(path) {
history.replaceState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
history.pushState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
listerPopState () {
window.addEventListener('popstate' , e => {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]()
})
}
}
// 使用 Router
window.miniRouter = new Router();
miniRouter.route('/', ()=> console.log('page1'))
miniRouter.route('/page2', ()=> console.log('page2'))
// 跳转
miniRouter.push('/page2') // page2
v-if和v-for的使用注意点
用在同一组件上,v-for
会优先于v-if
做解析,本身v-if
就消耗资源,如果循环次数非常多,那肯定是不行的。解决方案:
- 控制一个列表的显示可以将
v-if
写在template
上
<template v-if="isShow">
<p v-for="item in items">
</template>
- 利用计算属性或其他方案,将不需要显示的项过滤掉,看代码
computed: {
items: function() {
return this.list.filter(function (item) {
return item.isShow
})
}
}