2024年最新VUE3 学习记录,2024年最新hashmap数据结构面试

跳槽是每个人的职业生涯中都要经历的过程,不论你是搜索到的这篇文章还是无意中浏览到的这篇文章,希望你没有白白浪费停留在这里的时间,能给你接下来或者以后的笔试面试带来一些帮助。

也许是互联网未来10年中最好的一年。WINTER IS COMING。但是如果你不真正的自己去尝试尝试,你永远不知道市面上的行情如何。这次找工作下来,我自身感觉市场并没有那么可怕,也拿到了几个大厂的offer。在此进行一个总结,给自己,也希望能帮助到需要的同学。

面试准备

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

面试准备根据每个人掌握的知识不同,准备的时间也不一样。现在对于前端岗位,以前也许不是很重视算法这块,但是现在很多公司也都会考。建议大家平时有空的时候多刷刷leetcode。算法的准备时间比较长,是一个长期的过程。需要在掌握了大部分前端基础知识的情况下,再有针对性的去复习算法。面试的时候算法能做出来肯定加分,但做不出来也不会一票否决,面试官也会给你提供一些思路。

主页


### 6`  接口 泛型 自定义类型


person.ts



//1. 定义一个接口 用于限制person对象的具体属性
export interface Person{
id:string,
name:string,
age:number
}

//2. 一个自定义类型
//数组 方法一
// export type Persons = Array

//数组 方法二
export type Persons = Person[]


Person.vue



???

### 7` props的使用


#### 简单示例:


接收父类传过来的数据 defineProps([' '])


父类内容:



```

子类引用:

<script setup lang="ts" name="Person">
defineProps(['a'])
</script>

<template>
    {{ a }}
</template>
曾加难度:

接收数组

父类内容:

<script setup lang="ts">
import Person from "@/components/Person.vue";
import {type Persons} from '@/typedefine/person'
import {reactive} from "vue";


//定义数组数据
let persionList= reactive<Persons>([
  //let定义 persion名称 :Array数组 <person>泛型
  {id: '01', name: 'LiM', age: 19},
  {id: '02', name: 'Li', age: 18},
  {id: '03', name: 'L', age: 19}
])

console.log(persionList)
</script>

<template>
  <person a="哈哈哈哈" :list="persionList"/>
</template>

<style scoped>

</style>

子类内容:

<script setup lang="ts" name="Person">
import type {Persons} from "@/typedefine/person";

// //只接收list
// defineProps(['list'])

// //接收list + 限制类型
// defineProps<{ list: Persons }>()

// //接收list + 限制类型 + 限制必要性
// defineProps<{ list?: Persons }>()

//接收list + 限制类型 + 限制必要性 + 指定默认值
withDefaults(defineProps<{ list?: Persons }>(), {
  list: () => [{id: '00', name: '0号', age: 20}]
})

// //接收list 同时将props保存起来
// let x = defineProps(['list'])
</script>


<template>
  <div class="person">
    <ul>
      <li v-for="persionObj in list" :key="persionObj.id">
        {{ persionObj.name }} -- {{ persionObj.age }}
      </li>
    </ul>
  </div>
</template>


<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

8` 生命周期

概念:Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机, 调用特定的函数, 从而让开发者有机会在特定阶段运行自己的代码, 这些特定的函数统称为: 生命周期钩子

注意:

当引用组件时 子组件会优先于父组件进行挂载

用 v-if 来决定是否显示时 如果条件为false那么内容将会被销毁

用v-show来决定是否显示时 如果条件为false那么内容会被隐藏

8.1 Vue2生命周期

组件的生命周期: 四个周期 八个钩子

[时刻]                [调用特定函数]

–>创建(创建前 beforeCreate,         创建完毕 created)

–>挂载(创建前 beforeMount,          挂载完毕 mounted)

–>更新(创建前 beforeUpdate,        挂载完毕 update)

–>销毁(创建前 beforeDestroy,       销毁完毕 destroyed)

拓展: 用 v-if 来决定是否显示时 如果条件为false那么内容将会被销毁 但是如果用v-show则会隐藏

8.2 Vue3生命周期

组件的生命周期: 四个周期 八个钩子

[时刻]                [调用特定函数]

–>创建 setup函数(vue3推荐使用setup语法糖 所以setup都不需要在写了)

–>挂载(创建前 onBeforeMount,          挂载完毕 onMounted)

–>更新(创建前 onBeforeUpdate,        挂载完毕 onUpdate)

–>卸载(创建前 onBeforeUnmount,       销毁完毕 onUnmounted)

拓展: vue3调用函数需要在函数内写上回调函数 ()=>{ 这里面写你要写的东西 }

9`自定义Hooks

hooks 简单来说就是外联ts 把冗杂的ts内容(数据 函数 方法 钩子)单独存放,在需要的时候进行使用

9.1 创建一个文件夹名称为hooks

9.2 创建ts文件

axios 网络请求

安装: npm i axios (控制台)

引入: import axios from ‘axios’ (组件)

useDog.ts

import axios from "axios";
import {reactive} from "vue";

export default function () {
    //数据
    let dogList = reactive([
        'Https://api.dujin.org/pic'
    ])

    //函数
    async function getDog() {
        try {
            let result = await axios.get('Https://api.dujin.org/pic')
            dogList.push(result.data.message)
        } catch (error) {
            alert(error)
        }
    }
    //向外部提供信息
    return {dogList,getDog}
}

useSum.ts

import {ref} from "vue";

export default function () {
    //数据
    let sum = ref(0)

    //函数
    function changerSum() {
        sum.value++
    }
    return {sum,changerSum}
}
9.3在需要的时候使用

在vue组件内使用

import useSum from "@/hooks/useLoginIn";

const {sum,changerSum} = useSum()

二`路由

路由就是 一组 key 和 value 的对应关系( key + value => route) 多个路由由路由器管理

1.路由的基本切换效果

创建几个vue文件

@/router/index.ts

// 创建一个路由器 ,并暴露出去

//引入
import {createRouter, createWebHistory} from 'vue-router'

// 引入组件
import lable from '@/views/lable.vue'
import logHome from "@/views/log/logHome.vue";
import login from "@/views/log/page/login.vue";
import logon from "@/views/log/page/logon.vue";
import back from "@/views/log/page/back.vue";


// 创建路由
const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'lable',
            component: () => lable,
            // 标签页
        }, {
            path: '/log',
            name: 'log',
            component: () => logHome,
            // 登录注册页
            children: [
                {
                    path: '/log/login',
                    name: 'login',
                    component: () => login
                    //   登录页
                }, {
                    path: '/log/logon',
                    name: 'logon',
                    component: () => logon
                    //   注册页
                }, {
                    path: '/log/back',
                    name: 'back',
                    component: () => back
                    //   找回
                },
            ]
        }
    ]
})

// 暴露路由
export default router

main.ts

// 引入createApp用于创建应用
import { createApp } from 'vue'

// 引入App跟组件
import App from './App.vue'

// 引入路由
import router from './router'

// 使用路由
app.use(router)
// 挂载整个容器到app容器中
app.mount('#app')

vue.页面

<script setup lang="ts" name="Person">
//展示区占位RouterView 
import {RouterView,RouterLink} from "vue-router";


</script>


<template>
  <div class="person">
    <h2>VUE路由测试</h2>
<!--    导航区-->
    <div>
      <RouterLink to="/lable" active-class="/logHome">首页</RouterLink>
<!--      active-class="" 激活时展示样式-->
      <RouterLink to="/login">登录</RouterLink>
      <RouterLink to="/logon">注册</RouterLink>
      <RouterLink to="/back">找回</RouterLink>
    </div>
<!--    展示区-->
    <div>
      展示组件
      <RouterView/>
    </div>
  </div>
</template>


<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

2` 路由的两个注意点

1.路由组件通常存放在pages 或者 views文件夹 ,一般组件通常放在 components文件夹

路由组件: 靠路由的规则渲染出来的(不是通过标签展示出来的 比如: 这种的)

一般组件: 是咱们程序员亲手写的那种标签的组件

2.通过点击导航,视觉上"消失"了的路由组件 ,默认是被销毁掉的 ,需要的时候再去挂载

3` to的两种写法

基础写法:

1.字符串写法:登录

2.对象写法:   登录

传参写法:
query写法:
<div>
      <!--      路由传参-->
      <ul>
        <!--        方法一-->
        <li v-for=" item in newList " :key="item.id">
          <RouterLink :to="`/?id=${item.id}&title=${item.title}`">{{ item.title }}</RouterLink>
        </li>
        <!--        方法二-->
        <li v-for=" item in newList " :key="item.id">
          <RouterLink
              :to="{
                path:'/',
                query:{
                  id:item.id,
                  title:item.title
                }
              }">
            {{ item.title }}
          </RouterLink>
        </li>
      </ul>
    </div>

参数接收

<script setup lang="ts">
    let route = useRoute()
    let {query} = toRefs(route)
</script>

<template>
    <ul>
        <li>编号:{{router.id}}</li>
        <li>标题:{{router.title}}</li>
    </ul>
</template>
params写法:

备注1:传递params参数时 ,若使用to的对象写法,必须使用name配置项,不能用path

备注2:传递params参数时 ,需要提前在规则中占位

vue组件内:

<script setup lang="ts" name="Person">

</script>

<template>
  <div class="person">
    <h2>VUE路由测试</h2>
    <!--    导航区-->
    <div>
      <!--      路由传参-->
      <ul>
        <!--        方法一-->
        <li v-for=" item in newList " :key="item.id">
          <RouterLink :to="`/${item.id}/${item.title}`">{{ item.title }}</RouterLink>
        </li>
      </ul>
      <ul>
        <!--        方法二-->
        <li v-for=" item in newList " :key="item.id">
          <RouterLink 
            :to="{
                name:"/" 
<!--注意因为之前路径用占位了所以这块用name跳转 且不能传对象和数组-->
                params:{
                    id:item.id,
                    title:item.title
                }
            }"
           >
            
            {{ item.title }}</RouterLink>
        </li>
      </ul>
    </div>
    <!--    展示区-->
    <div>
      展示组件
      <RouterView/>
    </div>
  </div>
</template>


<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

路由文件内:

routes: [
        {
            path: '/:x/:y?',//:x为必须传的 :y?为可传可不传
            name: 'lable',
            component: () => lable,
            // 标签页
        }
        ]

参数接收

<script setup lang="ts">
    let route = useRoute()
    let {query} = toRefs(route)
</script>

<template>
    <ul>
        <li>编号:{{router.params.id}}</li>
        <li>标题:{{router.params.title}}</li>
    </ul>
</template>

4` 路由器的工作模式

history模式

写法:

vue2: mode:'hsitory

vue3: history:createWebHistory()

React: BrowserRouter 标签

优点:URL更加美观,不带有# ,更接近传统网站的URL

缺点:后期项目上线 ,需要服务端配合处理路径问题 ,否则刷新会有404错误

hash模式

写法:

vue2: mode:'hash

vue3: history:createWebHashHistory()

React: HashRouter 标签

优点:兼容性更好 ,因为不需要服务器端处理路径

缺点:URL带有#不太美观 ,且在SEO优化方面相对较差

`5 路由的props配置

作用:让路由组件更方便的收到参数(可以将路由参数作为 props 传给组件)

路由:

routes: [
        {
            path: '/:x/:y?',//:x为必须传的 :y?为可传可不传
            name: 'lable',
            component: () => logHome,//组件地址
            // 第一种写法,将路由收到的所有params参数作为props传给路由组件
            props:true

            // 第二种写法,可以自己决定将什么作为props传给路由组件
            // 对象写法
            // 比如传query的
            // props(route){
            //    return route.query
            // }
        }
        ]

组件:

<script setup lang="ts">
    defineProps(['id','title'])
</script>

<template>
    <ul>
        <li>编号:{{id}}</li>
        <li>标题:{title}}</li>
    </ul>
</template>

6` replace属性

push: 栈模式 可以 前进 后退(默认)

replace: 覆盖 不能 前进 后退 在

7` 编程试导航

脱离RouterLink实现跳转

路由组件的两个重要的属性: $route 和 $router 变成了两个 hooks

<script setup lang="ts" name="Person">

import {onMounted} from "vue";
import {useRouter} from "vue-router";

//路由器
const router = useRouter()

//组件挂在
onMounted(()=>{
  //展示事件
  setTimeout(()=>{
    //让路由实现跳转
    router.push('/')//push跳转 留下历史记录 可以前进 后退
    // router.replace('/')//replace跳转 不留记录
  },3000)//只能看3s
})
</script>

<template>
  <div class="person">

  </div>
</template>


<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

8` 路由的重定向

将本来应该跳转到/的跳转到/home那

routes: [
        {
            path: '/',
            name: 'lable',
            component: () => lable,
            // 标签页
        },{
            path: '/home',
            name: 'home',
            component: () => home,
            // 标签页
        },{
            path: '/',
            redirect: '/home'
        }
        ]

三` pinia 仓库

Pinia: 集中式状态(数据) 管理

1.搭建环境

下载: npm install pinia

main.ts

// 引入createApp用于创建应用
import {createApp} from 'vue'

//引入App跟组件
import App from './App.vue'

//引入pinia
import {createPinia} from 'pinia'

// 应用路由
const app = createApp(App)

// pinia注入
app.use(createPinia())

// 挂载整个容器到app容器中
app.mount('#app')

2.创建目录

创建一个目录名称为store

3.编写格式

count.ts

// 引入仓库
import {defineStore} from "pinia";

// 使用仓库 官方命名规则: use+文件名+Store
// defineStore参数1: id 推荐与文件名一致
// defineStore参数2: options 配置对象
export const useCountStore = defineStore('count',{
    
    // actions里面放置的是一给个的方法,用于相应组件种的"动作"
    actions:{
        increment(value){
            if(this.sum<10){
                console.log('此方法被调用',value)
                //修改数据
                this.sum+=value
            }
        }
    },
    //真正存储数据的地方
    state() {
        return{
            sum:7,
            school1:'辽工大',
            school2:'辽科大'
        }
    },
})

Count.vue

<script setup lang="ts" name="count">
import {ref} from "vue";
import {useCountStore} from "@/stores/count";

//数据
let n = ref(1)

//拿到数据并将其存入countStore
const countStore = useCountStore()

//函数
function add() {
  countStore.sum+=n.value
  console.log(n)
}


</script>

<template>
  <div class="person">
    <h2>当前求和为: {{ countStore.sum }}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">加</button>
  </div>
</template>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

4`修改数据的三种方式:

<script setup lang="ts" name="count">
import {ref} from "vue";
import {useCountStore} from "@/stores/count";

//数据
let n = ref(1)

//拿到数据并将其存入countStore
const countStore = useCountStore()

//函数
function add() {
  //第一种修改方式:直接修改
  // countStore.sum+=n.value
  // countStore.sum = '北大'
  // countStore.sum = '清华'

  //第二种修改方式:批量修改
  // countStore.$patch({
  //   sum:888,
  //   school1: '北大',
  //   school2: '郊大'
  // })

  //第三种修改方法:调用在count.ts已经定义好了的方法
  countStore.increment(n.value)
}


</script>

<template>
  <div class="person">
    <h2>当前求和为: {{ countStore.sum }}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">加</button>
  </div>
</template>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

5` storeToRefs 解构数据

将store内的数据结构出来(只解构其中的数据,不会对方法进行)

<script setup lang="ts" name="count">
import {ref} from "vue";
import {useCountStore} from "@/stores/count";
import {storeToRefs} from "pinia";

//数据
let n = ref(1)

//拿到数据并将其存入countStore
const countStore = useCountStore()

//解构
const {sum,school1,school2} = storeToRefs(countStore)

//函数
function add() {
  countStore.increment(n.value)
}


</script>

<template>
  <div class="person">
    <h2>当前求和为: {{ sum }}</h2>
    <h2>{{school1}}</h2>
    <h2>{{school2}}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">加</button>
  </div>
</template>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

6` getters 加工数据

count.ts

// 引入仓库
import {defineStore} from "pinia";
import {state} from "vue-tsc/out/shared";

// 使用仓库 官方命名规则: use+文件名+Store
// defineStore参数1: id 推荐与文件名一致
// defineStore参数2: options 配置对象
export const useCountStore = defineStore('count',{

    // actions里面放置的是一给个的方法,用于相应组件种的"动作"
    actions:{
        increment(value){
            if(this.sum<10){
                console.log('此方法被调用',value)
                //修改数据
                this.sum+=value
            }
        }
    },
    //真正存储数据的地方
    state() {
        return{
            sum:7,
            school1:'辽工大',
            school2:'辽科大'
        }
    },

    //加工数据
    getters:{
        bigSum:state => state.sum*10,
        upperSchool():string{
            return this.school1+'很好'
        }
    }
})

Count.vue

<script setup lang="ts" name="count">
import {ref} from "vue";
import {useCountStore} from "@/stores/count";
import {storeToRefs} from "pinia";

//数据
let n = ref(1)

//拿到数据并将其存入countStore
const countStore = useCountStore()

//解构
const {sum,school1,school2,bigSum} = storeToRefs(countStore)

//函数
function add() {
  countStore.increment(n.value)
}


</script>

<template>
  <div class="person">
    <h2>当前求和为: {{ sum }} 放大十倍后 {{bigSum}}</h2>
    <h2>{{school1}}</h2>
    <h2>{{school2}}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">加</button>
  </div>
</template>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

7` $subscribe

通过store的 $subcribe() 方法进行侦听 state 及其变化

<script setup lang="ts" name="count">
import {ref} from "vue";
import {useCountStore} from "@/stores/count";
import {storeToRefs} from "pinia";

//数据
let n = ref(1)

//拿到数据并将其存入countStore
const countStore = useCountStore()

//侦听
countStore.$subscribe((mutation, state)=>{
  console.log('数据发生变化'+'本次修改信息为:'+mutation+'侦听的数据'+state)
})

//解构
const {sum} = storeToRefs(countStore)

//函数
function add() {
  countStore.increment(n.value)
}


</script>

<template>
  <div class="person">
    <h2>当前求和为: {{ sum }}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
    </select>
    <button @click="add">加</button>
  </div>
</template>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

8` store组合式写法

// 引入仓库
import {defineStore} from "pinia";
import {reactive} from "vue";
import axios from "axios";

// 使用仓库 官方命名规则: use+文件名+Store
// defineStore参数1: id 推荐与文件名一致
// defineStore参数2: options 配置对象
export const useCountStore = defineStore('count', () => {
    let countList = reactive(
        JSON.parse(localStorage.getItem('countList') as string) || []
    )

    //相当于getCount函数,相当于action
    async function getCount(value: any) {
        // 发送请求,下面这行的写法是: 连续解构赋值+重命名
        let {data: {content: title}} = await axios.get('https://api.uomg.com/api/...........')
        //把请求回来的字符串,包装成一个对象
        let obj = {id:nanoid(),title}
        //放到数组中
        countList.unshift(obj)
    }
    return {countList,getCount}
})

四` 通讯组件

1` props:

父传子 直接传递非函数 ;子传父 传递一个函数给子子调用父给的函数

2` 自定义事件

传参数的同时保留传递事件对象

@click=“text(6,7,$event)”

自定义事件常用于子给父传值

子组件

<script setup lang="ts" name="Person">

// 声明事件
import {onMounted} from "vue";

const emit = defineEmits(['haha'])

onMounted(() => {
  setTimeout(() => {
    //触发haha
    emit('haha')
  }, 3000)
})
</script>

<template>
  <div class="person">
    <button @click="emit('haha')"></button>
  </div>
</template>


<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
</style>

父组件

<script setup lang="ts">
import router from "@/router";
import Person from "@/components/Person.vue";

function qwe() {
  console.log('qwe')
}
</script>

<template>
  <h1 ref="title2">主页</h1>

<!--  给子组件Person绑定事件-->
  <person @haha="qwe"/>
</template>

<style scoped>

</style>

3` mitt

安装:npm i mitt

mitt属于工具 存放于文件夹 utils/tools 中

于文件夹内新建文件emitter.ts

//引入mitt
import mitt from "mitt";


### ajax
1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?

![ajax.PNG](https://img-blog.csdnimg.cn/img_convert/5cabae7aa4de4ebf798029e548cf840a.webp?x-oss-process=image/format,png)

![前12.PNG](https://img-blog.csdnimg.cn/img_convert/ea139871b582836b40c4d47e5bb579af.webp?x-oss-process=image/format,png)

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

1` props:


父传子 直接传递非函数 ;子传父 传递一个函数给子子调用父给的函数


### 2` 自定义事件


传参数的同时保留传递事件对象



> 
> @click="text(6,7,$event)"
> 
> 
> 


自定义事件常用于子给父传值


子组件




父组件



主页

<person @haha=“qwe”/>


### 3` mitt



> 
> 安装:npm i mitt
> 
> 
> 


mitt属于工具 存放于文件夹 utils/tools 中


于文件夹内新建文件emitter.ts



//引入mitt
import mitt from “mitt”;

ajax

1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?

[外链图片转存中…(img-KddTSHYg-1715708675518)]

[外链图片转存中…(img-NzJIx2fP-1715708675519)]

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值