Vue3小兔鲜:组合式写法入门

news2024/12/25 8:58:47

Vue3:组合式写法入门

Date: May 11, 2023


认识Vue3

1. Vue3组合式API体验

通过 Counter 案例 体验Vue3新引入的组合式API

<script>
export default {
  data(){
    return {
      count:0
    }
  },
  methods:{
    addCount(){
      this.count++
    }
  }
}
</script>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = ()=> count.value++
</script>

特点:

  1. 代码量变少
  2. 分散式维护变成集中式维护 2. Vue3更多的优势


2. Vue3更多的优势

Untitled




使用create-vue搭建Vue3项目

1. 认识create-vue

create-vue是Vue官方新的脚手架工具,底层切换到了 vite (下一代前端工具链),为开发提供极速响应

https://cdn.nlark.com/yuque/0/2023/png/274425/1678178479590-ac164009-4a72-4448-85bf-67dc13f3d0c4.png#averageHue=%23feefbe&clientId=ud0819acc-4d21-4&from=paste&height=402&id=u05a93b8e&name=image.png&originHeight=804&originWidth=1606&originalType=binary&ratio=2&rotation=0&showTitle=false&size=221602&status=done&style=none&taskId=uf227924e-280a-4766-add6-d34b9331b0d&title=&width=803



2. 使用create-vue创建项目

前置条件 - 已安装16.0或更高版本的Node.js

执行如下命令,这一指令将会安装并执行 create-vue

npm init vue@latest

https://cdn.nlark.com/yuque/0/2023/png/274425/1678178685782-71a3b311-423d-4528-aae9-85e6068db452.png#averageHue=%23333332&clientId=ud0819acc-4d21-4&from=paste&height=477&id=u807a99d3&name=image.png&originHeight=954&originWidth=1364&originalType=binary&ratio=2&rotation=0&showTitle=false&size=488023&status=done&style=none&taskId=u4d75c82e-6b19-48a6-a9df-0ee44d9e92c&title=&width=682




熟悉项目和关键文件

image-20230530181407325




组合式API - setup选项

1. setup选项的写法和执行时机

写法

<script>
  export default {
    setup(){

    },
    beforeCreate(){

    }
  }
</script>

执行时机 > 在beforeCreate钩子之前执行

Untitled



2. setup中写代码的特点

在setup函数中写的数据和方法需要在末尾以对象的方式return,才能给模版使用

<script>
  export default {
    setup(){
      const message = 'this is message'
      const logMessage = ()=>{
        console.log(message)
      }
      // 必须return才可以
      return {
        message,
        logMessage
      }
    }
  }
</script>


3.

script标签添加 setup标记,不需要再写导出语句,默认会添加导出语句

<script setup>
  const message = 'this is message'
  const logMessage = ()=>{
    console.log(message)
  }
</script>

左边是采用语法糖的写法,右边是转译后的复杂写法:

Untitled

案例:

<template>
  <div>
    {{ message }}
    <button @click="logMessage">log</button>
  </div>
</template>

<script setup>
//采用setup方式:省略export default 与 return
  const message = 'this is message'
  const logMessage = () => {
    console.log(message);
  }
</script>

<style>

</style>

总结:

  1. setup选项的执行时机?
    1. beforecreate钩子之前 自动执行
  2. setup写代码的特点是什么?
    1. 定义数据+函数 然后以对象方式return



组合式API - reactive和ref函数

1. reactive

**作用:**接受对象类型数据的参数传入并返回一个响应式的对象

注:响应式对象可以引发视图的更新

核心步骤:

  1. 从 vue 包中导入 reactive 函数

<script setup>
// 导入
import {reactive} from 'vue'

// 执行函数 传入参数 变量接收
const state = reactive(对象类型数据)
</script>

案例:

<script setup>
  // 导入
  import { reactive } from 'vue' 
  // 执行函数 传入参数 变量接收
  const state = reactive({ //
    msg:'this is msg' //这里传入一个常规的对象
  })//通过reactive()会返回给state一个响应式对象
  const setState = ()=>{
    // 修改数据更新视图
    state.msg = 'this is new msg'
  }
</script>

<template>
  <p>{{ state.msg }}</p>
  <button @click="setState">change msg</button>
</template>

效果:

Untitled



2. ref

作用:接收简单类型或者对象类型的数据传入并返回一个响应式的对象

核心步骤:

  1. 从 vue 包中导入 ref 函数

<script setup>
// 导入
import { ref } from 'vue'

// 执行函数 传入参数 变量接收
const state = reactive(简单类型或者复杂类型数据)
</script>

案例:

<script setup>
 // 导入
 import { ref } from 'vue'
 // 执行函数 传入参数 变量接收
 const count = ref(0)
 const setCount = ()=>{
   // 修改数据更新视图必须加上.value
   count.value++
 } 
</script>

<template>
  <button @click="setCount">{{count}}</button>
</template>

效果:

Untitled

注意:打印通过ref创建的响应式对象

Untitled



3. reactive 对比 ref

二者基本作用:接收数据,返回响应式对象

响应式对象:可以引发视图的更新

  1. 都是用来生成响应式数据
  2. 不同点
    1. reactive不能处理简单类型的数据
    2. ref参数类型支持更好,但是必须通过.value做访问修改
    3. ref函数内部的实现依赖于reactive函数
  3. 在实际工作中的推荐
    1. 推荐使用ref函数,减少记忆负担,小兔鲜项目都使用ref



组合式API - computed

计算属性基本思想和Vue2保持一致,组合式API下的计算属性只是修改了API写法

核心步骤:

  1. 导入computed函数
  2. 执行函数在回调函数中return基于响应式数据做计算的值,用变量接收
<script setup>
	// 导入
	import {ref, computed } from 'vue'
	// 计算属性 变量接收 在回调参数中return计算值
	const computedList = computed(() => {
	    return 基于响应式数据做计算之后的值
	})
</script>

案例:

<template>
  <div>
    原始响应式数组 - {{ list }}
  </div>
  <div>
    计算属性数组 - {{ computedList }}
  </div>
</template>

<script setup>
  // 原始响应式数组
  import { ref } from 'vue'
  // 1. 导入computed
  import { computed } from 'vue'
  const list = ref([1, 2, 3, 4, 5, 6, 7, 8])
  // 2. 执行函数
  const computedList = computed(() => {
    return list.value.filter(item =>  item > 2)
  })
</script>

效果:

Untitled

总结:

最佳实践

  1. 计算属性中不应该有“副作用〞

    计算属性应该专注于数据的计算,而不应该处理如异步请求/修改dom等操作

  2. 避免直接修改计算属性的值

    计算属性应该是只读的,因此我们的计算属性一般用const修饰




组合式API - watch

**作用:**侦听一个或者多个数据的变化,数据变化时执行回调函数,

两个额外参数 immediate控制立刻执行,deep开启深度侦听

1. 侦听单个数据

具体步骤:

  1. 导入watph函数
  2. 执行watch函数传入要侦听的响应式数据(ref对象)和回调函数

案例:

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  // 2. 调用watch 侦听变化
  watch(count, (newValue, oldValue)=>{
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
  })
</script>

注意:watch中ref对象不需要加.value

效果:

Untitled



2. 侦听多个数据

侦听多个数据,第一个参数可以改写成数组的写法

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  const name = ref('cp')
  // 2. 调用watch 侦听变化
  watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
    console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])
  })
</script>

3. immediate

在侦听器创建时立即出发回调,响应式数据变化之后继续执行回调

案例:

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const count = ref(0)
  // 2. 调用watch 侦听变化
  watch(count, (newValue, oldValue)=>{
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
  },{
    immediate: true
  })
</script>

效果:

上来就会执行一次代码

Untitled



4. deep

**默认机制:**通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep

案例:

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const state = ref({ count: 0 })
  // 2. 监听对象state
  watch(state, ()=>{
    console.log('数据变化了')
  })
  const changeStateByCount = ()=>{
    // 直接修改不会引发回调执行
    state.value.count++
  } 
</script>

<script setup>
  // 1. 导入watch
  import { ref, watch } from 'vue'
  const state = ref({ count: 0 })
  // 2. 监听对象state 并开启deep
  watch(state, ()=>{
    console.log('数据变化了')
  },{deep:true})
  const changeStateByCount = ()=>{
    // 此时修改可以触发回调
    state.value.count++
  }
</script>

效果:

Untitled

注意:开启deep也会开启递归遍历,会带来额外的性能损耗,所以绝大情况下,不建议开启deep



5. 精确侦听对象的某个属性

**需求:**在不开启deep的前提下,侦听age的变化,只有age变化时才执行回调

具体操作:

如果你想要侦听某个属性,那就在watch中将第一个参数写成回调函数的写法

案例:

<template>
  <div>
    <p>当前name -- {{ state.name }}</p>
    <p>当前age -- {{ state.age }}</p>
    <hr/>
    <button @click="changeName">CName</button>
    <button @click="changeAge">CAge</button>
  </div>
</template>

<script setup>
  import { ref, watch } from 'vue'
  const state = ref({
    name: 'cp',
    age: 18,
  })
  const changeName = () => {
    state.value.name = "test"
  }
  const changeAge = () => {
    state.value.age = 20
  }

  watch(
    () => state.value.age, //要侦听谁就把谁写过来
    () => console.log('age发生变化了') //数据变化时要执行的回调
  )
</script>

效果:

Untitled

Untitled

总结:

  1. 作为watch函数的第一个参数,ref对象需要添加.value吗?

不需要,watch会自动读取

2.watch只能侦听单个数据吗?

单个或者多个

  1. 不开启deep,直接修改嵌套属性能触发回调吗?

    不能,默认是浅层侦听

  2. 不开启deep,想在某个层次比较深的属性变化时执行回调怎么做?

    可以把第一个参数写成函数的写法,返回要监听的具体属性




组合式API - 生命周期函数

1. 选项式对比组合式

Untitled

理解:

在组合式API中没有beforeCreate/create这两构造函数, 可以将原本的内容填入setup中



2. 生命周期函数基本使用

具体操作:

  1. 导入生命周期函数

  2. 执行生命周期函数,传入回调

<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})
</script>

**效果:**直接挂载并输出内容

Untitled



3. 执行多次

作用:生命周期函数执行多次的时候,会按照顺序依次执行

案例:

<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
  // 自定义逻辑
})

onMounted(()=>{
  // 自定义逻辑
})
</script>

效果:

如果遇到需要添加需求,我们又不想直接修改他人代码,

我们可以在下面在补充一个onMounted(),里面填写需要的补充逻辑。

Untitled

总结:

  1. 组合式API中生命周期函数的格式是什么?

    on+生命周期名字

  2. 组合式AP1中可以使用oncreated吗?

    没有这个钩子西数,直接写到setup中

  3. 组合式AP1中组件卸载完毕时执行哪个函数?

    onUnmounted




组合式API - 父子通信

1. 父传子

基本思想:

  1. 父组件中给子组件绑定属性

  2. 子组件内部通过props选项接收数据

具体操作:

父组件:绑定属性

子组件:通过 defineProps ( 编译器宏函数) 接收子组件传递的数据

Untitled

案例:

补充:这里添加了响应式数据的父传子的方式,即需要在组件中的属性前加上:

App.vue

<template>
  <div class="father">
    <h2>父组件App</h2>
    <!-- 1. 绑定属性 -->
    <son-com :count="count" message="father message"></son-com>
  </div>
</template>

<script setup>
import { ref } from 'vue'
// setup语法糖下局部组件无需注册直接可以使用
import SonCom from './components/son.vue'
const count = ref(100)
</script>

son.vue

<template>
  <div class="son">
    <h3>子组件Son</h3>
    <div>
      父组件传入的数据 - {{ message }} - {{ count }}
    </div>
  </div>
</template>

<script setup>
//2. defineProps接收数据
defineProps({
  message: String,
  count: Number,
})
</script>

效果:

Untitled

拓展理解:关于编译器宏函数

我们将代码放到Vue SFC Playground中,可以发现defineProps实际上是个标志,当代码编译时,会把左边的代码编译成右边我们熟悉的代码。

Untitled



2. 子传父

基本思想:

  1. 父组件中给子组件标签通过@绑定事件 2. 子组件内部通过 emit 方法触发事件

具体操作:

  1. 父组件绑定自定义事件
  2. 通过defineEmits编译器宏生成emit方法
  3. 触发自定义事件,并传递参数

Untitled

Untitled

总结:

父传子

  1. 父传子的过程中通过什么方式接收props?
    defineProps({属性名:类型})
  2. setup语法糖中如何使用父组件传过来的数据?
    const props =defineProps( {属性名:类型})

子传父

1.子传父的过程中通过什么方式得到emit方法?

defineEmits(['事件名称’])




组合式API - 模版引用 (这一块需要再看看)

概念:通过 ref标识 获取真实的 dom对象或者组件实例对象

1. 基本使用

实现步骤: 1. 调用ref函数生成一个ref对象 2. 通过ref标识绑定ref对象到标签

代码演示:

<script setup>
  // 1. 调用ref函数 -> ref对象
  const h1Ref = ref(null)
</script>

<template>
  <!-- 2. 通过ref标识绑定ref对象 -->
  <h1 ref="h1Ref">我是dom标签</h1>
</template>

理解:通过1和2两步,dom对象已经被存到了h1Ref.value身上

案例:

如果我们想要获取数据(比如h1.value),需要等到组件挂载完毕之后才能获取

<template>
  <!-- 2. 通过ref标识绑定ref对象 -->
  <h1 ref="h1Ref">我是dom标签1</h1>
  <test-com></test-com>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import TestCom from './components/son.vue'
// 1. 调用ref函数 -> ref对象
const h1Ref = ref(null)
const comRef = ref(null)

// 组件挂载完毕之后才能获取
onMounted(() => {
  console.log(h1Ref.value)
  console.log(TestCom.value)
})
</script>


2. defineExpose

默认情况下在

说明:指定testMessage属性可以被访问到

Untitled

总结:

  1. 获取模板引用的时机是什么?
    组件挂载完毕
  2. defineExpose编译宏的作用是什么?
    显式暴露组件内部的属性和方法



组合式API - provide和inject

1. 作用和场景

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信

image-20230530181607112

理解:room-page称为顶层组件,room-msg-comment称为底层组件



2. 跨层传递普通数据

实现步骤:

  1. 顶层组件通过 provide 函数提供数据
  2. 底层组件通过 inject 函数提供数据

顶层组件:

provide('key', 顶层组件中的数据)

底层组件:

const message = inject('key')

注意:以上二者的key相互关联

案例:

Untitled

效果:

Untitled



3. 跨层传递响应式数据

具体操作:在调用provide函数时,第二个参数设置为ref对象
顶层组件:

provide('app-key', ref对象)

底层组件:

const message = inject('app-key')

案例:

Untitled

效果:

Untitled



4. 跨层传递方法

逻辑:顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据

顶层组件:

const setCount = () => {
	count.value++
}
provide('setCount-key', setCount)

底层组件:

const setCount = inject('setCount-key')

案例:

Untitled

效果:点击按钮,顶层组件的响应式数据会变化

Untitled

总结:

需求1: 我们需要从顶层传递订单id等信息到底层组件

顶层提供provide(’id-key’, orderId),底层采用 inject(’id-key’) 接收,从而实现顶层数据向底层的传递。

Untitled

需求2: 底层通知顶层评价完毕

顶层提供provide(’state-fn’, changeState)传递函数, 底层通过inject(’state-fn’) → changeState()接收函数并调用,从而实现对顶层数据的修改

Q&A:

  1. provide和inject的作用是什么?
    跨层组件通信
  2. 如何在传递的过程中保持数据响应式?
    第二个参数传递ref对象
  3. 底层组件想要通知顶层组件做修改,如何做?
    传递方法,底层组件调用方法
  4. 一颗组件树中只有一个顶层或底层组件吗?
    相对概念,存在多个顶层和底层的关系



综合案例

案例演示:

image-20230530181644050

1. 项目地址

git clone  http://git.itcast.cn/heimaqianduan/vue3-basic-project.git

2. 项目说明

  1. 模版已经配置好了案例必须的安装包
  2. 案例用到的接口在 README.MD文件 中
  3. 案例项目有俩个分支,main主分支为开发分支,complete分支为完成版分支供开发完参考

3. 项目实现:

步骤1: 列表渲染

效果:

Untitled

实现:

// TODO1: 列表渲染
// 思路:声明响应式list -> 调用接口获取数据 -> 后端数据赋值给list -> 绑定到table组件

// 具体步骤:
const list = ref([])
// 1.调用发送的异步请求
const getList = async () => {
  // 接口调用
  const res = await axios.get('/list')
  // 交给list
  list.value = res.data
}
onMounted( () => getList())

说明:我们将数据传输给相应的列表

Untitled

步骤2: 删除功能

效果:

Untitled

实现:

// TODO: 删除功能
// 思路:获取当前行的id -> 通过id调用删除接口 -> 更新最新的列表
const onDelete = async (id) => {
  console.log(id);
  await axios.delete(`/del/${id}`)
  getList()
}

说明:

Untitled

步骤3: 编辑功能

效果:

Untitled

实现:

主组件:

// TODO: 编辑功能
// 思路:打开弹窗 -> 回填数据 -> 更新数据
// 1. 打开弹窗 (获取子组件实例 调用方法或者修改属性)
const editRef = ref(null)
const onEdit = (row) => {
  editRef.value.open(row)
}
// 2. 回调数据 (调用详情接口 / 当前行的静态数据)

编辑功能组件:

<script setup>
// TODO: 编辑
import { ref } from 'vue'
import axios from 'axios';
// 弹框开关
const dialogVisible = ref(false)
// 准备form
const form = ref({
  name: '',
  place: '',
  id: ''
})
const open = (row) => {
  console.log(row)
  form.value.name = row.name
  form.value.place = row.place
  form.value.id = row.id
  dialogVisible.value = true
}
defineExpose({
  open
})

// 更新
const emit = defineEmits(['on-update'])
const onUpdata = async () => {
  // 1. 收集表单数据,调用接口
  await axios.patch(`/edit/${form.value.id}`, {
    name: form.value.name,
    place: form.value.place,
  })
  // 2. 关闭弹窗
  dialogVisible.value = false
  // 3. 通知父组件做列表更新
  emit('on-update')
}
</script>

<template>
  <el-dialog v-model="dialogVisible" title="编辑" width="400px">
    <el-form label-width="50px">
      <el-form-item label="姓名">
        <el-input placeholder="请输入姓名" v-model="form.name"/>
      </el-form-item>
      <el-form-item label="籍贯">
        <el-input placeholder="请输入籍贯" v-model="form.place"/>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="onUpdata">确认</el-button>
      </span>
    </template>
  </el-dialog>
</template>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/604016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaSE】Java基础语法(四十四):XML解析

文章目录 1. 概述2.标签的规则3. 语法规则【应用】4. xml解析【应用】 1. 概述 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年&#xff0c;又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者&#xff1a; Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域…

【分布族谱】高斯分布和逆高斯分布的关系

文章目录 高斯分布逆高斯分布简介通过高斯分布构造逆高斯分布 高斯分布 正态分布&#xff0c;又称Gauss分布&#xff0c;其概率密度函数入下图所示 正态分布 N ( μ , σ ) N(\mu, \sigma) N(μ,σ)受到期望 μ \mu μ和方差 σ 2 \sigma^2 σ2的调控&#xff0c;其概率密度函…

基于SpringBoot+Vue的医疗服务系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

Qt for Android环境配置(联合Android Studio)

目录 1.安装JDK2.安装Android Studio并下载必要组件3.安装QtCreator并配置 Official Doc 1.安装JDK Oracle JDK Download 配置环境变量&#xff1a; 2.安装Android Studio并下载必要组件 Android Studio Download 下图中&#xff0c;31.0.0是当前Qt必需的&#xff0c;3…

chatgpt赋能python:Python制作抽奖——让你的活动更有趣

Python制作抽奖——让你的活动更有趣 在活动中&#xff0c;抽奖环节常常是一大亮点。而用Python制作抽奖程序&#xff0c;则可以更灵活、更实用地完成这个环节。接下来我们将介绍Python制作抽奖的方法&#xff0c;并且说明如何让你的抽奖环节更加有趣。 Python制作抽奖的方法…

【Linux网络服务】Nginx优化

Nginx网页优化 一、配置Nginx网页缓存时间1.1设置方法 二、隐藏Nginx版本号2.1方法一&#xff1a;修改配置文件2.2方法二&#xff1a;修改源码文件&#xff0c;重新编译 三、修改用户与组四、日志切割五、连接超时六、更改进程数七、网页压缩八、配置防盗链九、Linux内核参数优…

华为OD机试真题 Java 实现【素数之积】【2022Q4 100分】

一、题目描述 RSA加密算法在网络安全世界中无处不在&#xff0c;它利用了极大整数因数分解的困难度&#xff0c;数据越大&#xff0c;安全系数越高。 给定一个32位正整数&#xff0c;请对其进行因数分解&#xff0c;找出是哪两个素数的乘积。 二、输入描述 一个正整数num …

基于物理信息的神经网络(Physics-informed Neural Networks;PINNs)Part-1(简单介绍)

【摘要】 基于物理信息的神经网络&#xff08;Physics-informed Neural Networks&#xff0c;简称PINNs&#xff09;&#xff0c;是一类用于解决有监督学习任务的神经网络&#xff0c;它不仅能够像传统神经网络一样学习到训练数据样本的分布规律&#xff0c;而且能够学习到数学…

段的概念-汇编复习(3)

本文小节讨论内容&#xff1a;"段地址x16偏移地址物理地址”的本质含义,段 的 概 念 "段地址x16偏移地址物理地址”的本质含义 注意&#xff0c;这里讨论的是 8086CPU 段地址和偏移地址的本质含义&#xff0c;而不是为了解决具体的问题而在本质含义之上引申出来的更…

Node.js基本概念、特点、用途和常用模块,以及Express框架开发一个web应用

目录 一、Node.js的基本概念和特点 二、Node.js的用途 三、Node.js的常用模块 四、使用Node.js进行Web开发 1. 安装Node.js 2. PyCharm配置Node.js 3. 使用http库编写一个web服务 4. 使用Express框架构建Web应用程序 5. 调试代码 6. 发布应用程序 参考文章 Node.js是…

[转载]Nginx 使用 X-Accel-Redirect 实现静态文件下载的统计、鉴权、防盗链、限速等

需求 统计静态文件的下载次数&#xff1b;判断用户是否有下载权限&#xff1b;根据用户指定下载速度&#xff1b;根据Referer判断是否需要防盗链&#xff1b;根据用户属性限制下载速度&#xff1b; X-Accel-Redirect This allows you to handle authentication, logging or …

基于vue3全新后台管理方案vite4+vue3+pinia2+vue-i18n

Vite4-Admin 基于 vue3vite4.xpinia2vue-router4 构建后台管理系统。 支持vue-i18n国际化多语言、动态路由鉴权、4种布局模板及tab页面缓存等功能。 技术框架 编码器&#xff1a;VScode框架技术&#xff1a;vite4vue3piniavue-routerUI组件库&#xff1a;ve-plus (基于vue3自研…

PHP快速实战19-PHP使用IMAP获取QQ邮箱的收件列表及内容

文章目录 前言关于IMAP协议安裝与实现步骤1&#xff1a;安装IAMP扩展1.1 检查IMAP是否已安装1.2 安装IMAP扩展1.3 启用IMAP扩展1.4 重启服务 步骤2&#xff1a;开始功能实现2.1 开始编码2.2 代码执行 常见的20个PHP中IMAP方法总结 前言 本文已收录于PHP全栈系列专栏&#xff1…

详解js中的浅拷贝与深拷贝

详解js中的浅拷贝与深拷贝 1、前言1.1 栈&#xff08;stack&#xff09;和堆&#xff08;heap&#xff09;1.2 基本数据类型和引用数据类型1.2.1 概念1.2.2 区别1.2.3 基本类型赋值方式1.2.4 引用类型赋值方式 2、浅拷贝2.1 概念2.2 常见的浅拷贝方法2.2.1 Object.assign()2.2.…

25 strlen 的调试

前言 同样是一个 很常用的 glibc 库函数 不管是 用户业务代码 还是 很多类库的代码, 基本上都会用到 字符串长度的计算 不过 我们这里是从 具体的实现 来看一下 它的实现 主要是使用 汇编 来进行实现的, 因此 理解需要一定的基础 测试用例 就是简单的使用了一下 strc…

Vscode搭建开发调试STM32/RISC-V环境IDE(最全面)

单片机开发IDE环境如KeilMDK&#xff0c;虽然操作简单&#xff0c;方便调试。但就是代码编辑风格很老套&#xff0c;中文符号乱码还是常有的事。而如今流行的vscode编辑器很不错&#xff0c;免费且相当轻量级&#xff0c;用来代码开发体验很不错&#xff0c;看着都舒服。Clion …

【数学建模实例之SEIR】

学习数学建模: 从基础到实践 引言 在我们日常生活中&#xff0c;数学建模&#xff08;Mathematical Modeling&#xff09;是一个非常重要的工具&#xff0c;它帮助我们理解复杂的问题&#xff0c;并找到解决这些问题的方法。在这篇博客中&#xff0c;我们将探讨数学建模的基本…

深入理解计算机系统——汇编基础

文章目录 寄存器数据格式mov操作 push&#xff0c;popcall&#xff0c;retleave,enter算术和逻辑操作一元操作二元操作移位操作 特殊的算术操作控制条件码访问条件码跳转很好的例题 翻译条件分支循环条件传送指令switch例 函数堆栈递归的过程 数组数据结构结构体联合 使用GDB调…

信息与编码SCUEC DDDD 期末复习整理(1)

1.1948年&#xff0c;美国数学家香农发表了题为“通信的数学原理”的论文&#xff0c;从而创立了信息论。 2.不可能事件的自信息量是&#xff08;∞&#xff09;&#xff0c;必然事件的自信息量是&#xff08;0&#xff09; 3. 4.差错控制的主要方式有前向纠错方式FEC&#x…

线程的创建(Runnable,Future,CompletionService,CompletableFuture的辨析)

直接使用Thread 直接让某个类继承Thread类&#xff0c;复写run方法&#xff0c;外部调用的时候直接调用start方法。 因为java的单继承模式&#xff0c;但是我们一般不直接使用这种方法。 使用Runnable Slf4j public class MyTask implements Runnable {Overridepublic void …