前端面试题(代码版)持续更新

1.vue

1.1事件修饰符

1.1.1 阻止冒泡

		<div v-on:click='handle0'>{{num}}
			<button v-on:click.stop='handle1'>123</button>
		</div>


        在vue中,如果是同一事件(都是click),我们点击子组件的时候,父组件的click事件也会触发。
        如果我们只想让子组件触发,我们应该在子组件上加一个.stop来阻止事件冒泡。那么就只会子组件触发了。
        
        但是如果事件不相同的话,那么.stop也是没用的。
        <div v-on:onmouseup ='handle0'>{{num}}
			<button v-on:click.stop='handle1'>123</button>
		</div>

        那么怎么阻止他呢?可以再给子组件一个和父组件相同的事件,加上.stop即可
        <div v-on:onmouseup ='handle0'>{{num}}
			<button v-on:click.stop='handle1' v-on:onmouseup.stop>123</button>
		</div>

1.1.2 阻止默认行为

<a v-on:click.prevent href="http://www.hao123.com">1233</a>

1.2 组件传值

1.2.1子组件向父组件传值

子组件  在事件里面 '$emit("事件名",传的值)'
		 <button @click='$emit("enlarge-text",5)'>按钮</button>

父组件  引入子组件后  @事件名='函数($event)'   $event 是固定写法 就是传过来的值  那么接下来在函数中用形参接收就可以用了   
        <son @enlarge-text='handle5($event)'></son>

        		methods: {
			handle5:function(event){
				this.fontSize1 += event
			}

1.3 组件插槽

1.3.1  slot插槽

	子组件  本身有一些固定的样式  slot是为了父组件传递内容过来   被子组件这些固定样式包住设计的

    <view class="">
		每一次引用子组件 都会有的固定内容
		 <slot>默认内容</slot>
	</view>


    父组件 直接把这些内容写在  子组件标签   传过去即可
		<son>
			<view>我是父组件传递过来的内容</view>
		</son>

    

1.3.2 slot 具名插槽

// 子组件给slot 写一个名字  让父组件穿过来的内容 有相对应的位置
 
	<view class="">
		每一次引用子组件 都会有的固定内容
		 <slot name='header'></slot>
		 <slot></slot>
		 <slot name='footer'></slot>
	</view>

//父组件  调用子组件的时候 在里面写上 slot 并把名字写进去 那么就可以匹配到了
 
    	<son>
			<view slot="header">我是父组件传过来的标题信息</view>
			<view>我是父组件传过来的中间内容信息</view>
			<view slot="footer">我是父组件传过来的底部信息</view>
		</son>

1.4 异步编程

1.4.1 promise

// 先新建设一个函数 topList() 里面有一个promise对象

 export function topList(){
	// 这个函数会return一个值 是promise
	
	return new Promise(function (resolve, reject) {
        //接下来写异步任务
        // 在书写了代码逻辑以后  我们 就把正确的值 放在resolve('')里面  而错误写在reject里面,方便调用者使用
        setTimeout(function () {
          var flag = false;
          if (flag) {
            // 正常情况 把这个值传给then
            resolve('hello');
          } else {
            //异常情况  把这个传给then
            reject('出错了');
          }
        }, 100)
}

所以上述代码的的流程就是 你调用topList() 其实就是返回了 一个 promise对象给你  ,promise对象怎么用呢?

// 我们可以用.then来接收res ,这个就是 resolve 传出来的值
			topList().then((res)=>{
				if(res.length){
					this.topList=res;
					console.log(this.topList)
				}
				this.isLoading=false
			});


如何解决对调地狱呢?(有顺序的异步请求,但是代码又很优雅)
topList()
.then((res)=>{
    this.topList=res;
// 我们在这里面又请求  又会返回一个promise 对象 又然后又可以.then  然后无限循环
    return topList()
})
.then((res)=>{
    this.topList=res;
    return topList()
})


那么如何获取错误呢?
我们在promise对象里面reject('出错了') 的这个数据;
使用 .catch 来获取 

topList()
.then(function (value) {
    console.log("a / b = " + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {

finally 是一个最后都会调用的方法 不会传递数据进去




1.5 VUE-router

创建路由链接  会被渲染成a链接
<router-link to="/user"></router-link>

路由占位符 路由页面的内容将会放在这里展示
    <router-view></router-view>

创建路由实例对象
const routes = [
  {
    path: '/',
    name: 'home',
//只能放路由实例对象
    component: HomeView
  },
  {
    path: '/about',

    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

并且挂载
const router = new VueRouter({
  routes
})

1.5.1 路由动态匹配


<router-link to="/user/1"></router-link>
<router-link to="/user/2"></router-link>
<router-link to="/user/3"></router-link>

如果有100个用户要写一百个路由规则很不方便,使用:id 做占位符
const routes = [
  {
    path: '/user/:id',
    name: 'home',
//放组件  
    component: HomeView
  },
]


组件可以通过{{$route.params.id}} 拿到值
{{$route.params.id}} 可以通过{{$route.params.占位符}}获取值?

1.5.2 路由传参

1, 使用props传参

<router-link to="/user/1"></router-link>
<router-link to="/user/2"></router-link>
<router-link to="/user/3"></router-link>

组件内部  写一个props:['id'], 就可以直接{{id}}了
const user={
props:['id'],
tempalte:'<h1>{{id}}</h1>'

// props:true 开启路由传参
const routes = [
  {
    path: '/user/:id',
    name: 'home',
    component: HomeView
    props:true
  },
]



2, 使用props传参是对象的情况  但是这样我们的id就得不到了
<router-link to="/user/1"></router-link>
<router-link to="/user/2"></router-link>
<router-link to="/user/3"></router-link>

const user={
props:['uanem','age'],
tempalte:'<h1>{{uname}}{{age}}</h1>'

// props:true 开启路由传参
const routes = [
  {
    path: '/user/:id',
    name: 'home',
    component: HomeView
    props:{{uanem:'lisi',age:20}}
  },
]

3, 使用props传参是函数的情况  这样我们的id就可以获取到了
<router-link to="/user/1"></router-link>
<router-link to="/user/2"></router-link>
<router-link to="/user/3"></router-link>

const user={
props:['uanem','age','id'],
tempalte:'<h1>{{uname}}{{age}}{{id}}</h1>'

// props:true 开启路由传参
const routes = [
  {
    path: '/user/:id',
    name: 'home',
    component: HomeView,
    //route 是路由对象
    props:route=>{{uanem:'lisi',age:20,id:route.params.id}}
  },
]

1.5.3 命名路由

:to="{name:'user',params:{id:3}} 加个冒号变成对象,并且用params传参数
并且name和下面的name 相匹配  就是取个名字 用名字跳转的意思

<router-link to="/user/1"></router-link>
<router-link to="/user/2"></router-link>
<router-link :to="{name:'home',params:{id:3}}"></router-link>

组件内部  写一个props:['id'], 就可以直接{{id}}了
const user={
props:['id'],
tempalte:'<h1>{{id}}</h1>'

// props:true 开启路由传参
const routes = [
  {
    path: '/user/:id',
    name: 'home',
    component: HomeView
    props:true
  },
]

1.5.4 编程式导航

这个方法就可以跳转页面了
methods:{
goregister(){
    this.$router.push('/register')
}

2 js 算法

2.1 如何从数组中获取出现次数最多的那个值

// let a = [1,2,3,3,2,2,3,12,33,12,12,33]
let a = ['哈哈','66','哈哈','哈哈','66','嘿嘿','嘿嘿','嘿嘿','耶耶','耶耶']

let obj = {} //采用键值对来存储,键表示该数字,值表示给数字出现次数
let maxNum = 0
a.forEach((item, index) => {
	// 数组indexof(想要查找的对象) 返回的是第一次 这个值的位置
	// 如果这个位置和Index 相同  那么他第一次出现  给obj[item]这个属性名 一个1
  if(a.indexOf(item) == index){
	  obj[item] = 1
	//   如果此时这个值再出现 和 index 不同
	//   index 大于 item的第一次位置
	//   那么就给这个obj[item]这个属性名 +1
  }else{
    obj[item] = obj[item] + 1
  }
})
// 找出谁是最大值
// 我们for in 以下这个对象
// 如果obj第i个值 大于最大值  那么就赋值给他
for(let i in obj){
  if(obj[i] > maxNum){
    maxNum = obj[i]
  }
}

//根据最大值输出对应的数字
// 这个j是属性名  ,obj[j] 就是对象.属性名 就是属性值
for(let j in obj){
	if (obj[j] === maxNum) {
		console.log(obj[j]);
    console.log('出现次数最多的数字为',j,' ,次数为',obj[j]);
  }
}

2.2快速排序

Array.prototype.quickSort = function() {
    const rec = (arr) => {
        // 递归都是要有尽头的,不然会无限进行下去
        // 直到Maximum call stack size exceeded
        // 别问我为什么知道
        // 而且注意,这里要有小于1,不然也会报错
        if(arr.length <= 1) return arr;
        let left = []; //小于基准值的数组
        let right = []; //大于基准值的数组
        const base = arr[0]; //基准值
        // 因为基准线是arr[0],所以从下标是1也就是第二个开始
        for(let i = 1; i < arr.length; i += 1) {
            if(arr[i] < base) {
                left.push(arr[i])
            } else {
                right.push(arr[i])
            }
        }
        // 解构一下  ... 
        // 递归左边数组和右边数组    递归就是在函数里面再次调用函数
        // 左边加上右边加上基准才是完整数组哈   即可拼接【解构左数组,基准值,解构右数组】
        return [...rec(left), base, ...rec(right)];
    }

    const res = rec(this); //rec是一个递归  我们传入this this 是调用这个方法的数组本身,然后返回一个已经排序好的数组 使用res接收

    // 遍历res,赋值到this也就是当前数组本身  我们又把这个排序好的新数组 赋值给调用我们的数组上面 
    res.forEach((item, key) => {
        this[key] = item;
    })
}

const arr = [1, 5, 9, 3, 18, 6, 2, 7]
arr.quickSort()
console.log(arr);

3 js

3.1指向问题

3.1.1 call() 和 apply() 的区别

obj1.(method).call(obj2,argument1,argument2)

call的作用就是把obj1的方法放到obj2上使用,后面的argument1..这些做为参数传入。




function add (x, y) 
{ 
    console.log (x + y);
} 
function minus (x, y) 
{ 
    console.log (x - y); 
} 
add.call (minus , 1, 1);    //2


这个例子中的意思就是用 add 来替换 minus ,add.call(minus ,1,1) == add(1,1) ,所以运行结果为:console.log (2); 

A.call( B,x,y ):就是把A的函数放到B中运行,x 和 y 是A方法的参数。
用call来实现继承,用this可以继承myfunc1中的所有方法和属性。
应用场景

function myfunc1(){
    this.name = 'Lee';
    this.myTxt = function(txt) {
        console.log( 'i am',txt );
    }
}


function myfunc2(){
    myfunc1.call(this);
}

var myfunc3 = new myfunc2();
myfunc3.myTxt('Geing'); // i am Geing
console.log (myfunc3.name);	// Lee

3.2异步

3.2.1 async

如果仅仅使用async 写在函数前面的话
那么你调用函数获取的值将会是一个promise 对象

async function testAsy(){
   return 'hello world';
}
let result = testAsy(); 
console.log(result)   //result 为Promise对象


所以,我们不用await 的话 我们应该在调用这个值的使用使用.then方法

result.then(v=>{
    console.log(v)   // hello world
})


那么await 应该如何使用呢
我们来看一下await的解释
**await 在等待什么呢?**一般来说,都认为 await 是在等待一个 async 函数完成。不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,就是没有特殊限定)。
并且 语法上强制规定await只能出现在asnyc函数中

我们来看一个例子

// 首先是一个是一个promise对象
function testAsy(x){
   return new Promise(resolve=>{setTimeout(() => {
       resolve(x);
     }, 3000)
    }
   )
}

// 然后我们多写一个函数 包住我们要调用并返回promise 对象的函数 也就是async function testAwt(){    
//然后我们 就可以使用await 来调用 上面那个函数了 并且返回的值他已经不是primose对象 已经被awaiT解析了
//而且写await还有一个好处 ,那么就是下面的表达式必须等待 我们await 执行完才能接着执行

async function testAwt(){    
  let result =  await testAsy('hello world');
  console.log(result);    // 3秒钟之后出现hello world
  console.log('cuger')   // 3秒钟之后出现cug
}


testAwt();
console.log('cug')  //立即输出cug


那么为什么语法上强制规定await只能出现在asnyc函数中
因为上面的例子也可以看出,因为async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行,如果await写在同步函数中,那么就会阻塞后面的代码执行

3.2.2 如何使用try catch
 

	try{
		代码块;
		代码  throw"字符"   //抛出错误
	}catch(参数){				//抓住throw抛出的错误
			//处理错误并执行
	}finally{
			//无论try catch结果如何还是继续执行
	}


实例


 <p>请输出一个 5 到 10 之间的数字:</p>
	<input id="demo" type="text">
	<button type="button" @click="myFunction()">测试输入</button>
	<p id="mess"></p>
	
 myFunction(){
       var x=document.getElementById("demo").value;
       var y=document.getElementById("mess");
    	try{ 
         // 取元素的值
        if(x=="")    throw "值为空";       //根据获取的值,抛出错误
        if(isNaN(x)) throw "不是数字";
        if(x>10)     throw "太大";
        if(x<5)      throw "太小";
    }
    catch(err){
            
        y.innerHTML="错误:" + err + "。";  //抓住上面throw抛出的错误,给p标签显示
    } finally {
        x.value = "";
        if(x>4&&x<11){
          console.log("452")
           y.innerHTML = "";
    }
        }
       
    },

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值