vue3常用API之学习笔记
目录
一、setup函数
vue2与vue3变量区别
二、生命周期
三、reactive方法
四、ref方法
1、简介
2、使用
3、ref与reactive
4、获取标签元素或组件
五、toRef
1、简介
2、ref与toRef的区别
六、toRefs
七、shallowReactive 浅reactive
1、简介
2、shallowreactived的浅reactive
八、shallowRef
1、简介
2、triggerRef
九、toRaw方法
十、markRaw
十一、provide && inject
1、简介
2、代码实例
十二、watch && watchEffect
1、watch 简介
2、watchEffect与 watch 的区别
十三、getCurrentInstance
1、输出值ctx
2、输出值proxy
十四、useStore
一、setup函数
<template><div id="app"><p>{{ number }}</p><button @click="add">增加</button></div>
</template><script>
// 1. 从 vue 中引入 ref 函数
import {ref} from 'vue'
export default {name: 'App',setup() {// 2. 用 ref 函数包装一个响应式变量 numberlet number = ref(0)// 3. 设定一个方法function add() {// number是被ref函数包装过了的,其值保存在.value中number.value ++}// 4. 将 number 和 add 返回出去,供template中使用return {number, add}}}
</script>
vue2与vue3变量区别
1、vue2访问data或props中的变量,需要通过this
2、vue3的setup函数有两个参数,分别是props、context
(1)props:存储定义当前组件允许外界传递来的参数名及参数值
(2)context:上下文对象,能从中访问到attr、emit、slots
【emit就是vue2中父组件通信的方法,可以直接拿来调用】
二、生命周期
Vue2 | Vue3 |
---|---|
beforeCreate | setup |
created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestory | onBeforeUnmount |
destoryed | onUnmounted |
vue3生命周期的使用,也是先从vue中导入,再进行直接调用
<template><div id="app"></div>
</template><script>
// 1. 从 vue 中引入 多个生命周期函数
import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, unMounted} from 'vue'
export default {name: 'App',setup() {onBeforeMount(() => {// 在挂载前执行某些代码})onMounted(() => {// 在挂载后执行某些代码})onBeforeUpdate(() => {// 在更新前前执行某些代码})onUpdated(() => {// 在更新后执行某些代码})onBeforeUnmount(() => {// 在组件销毁前执行某些代码})unMounted(() => {// 在组件销毁后执行某些代码})return {}}}
</script>
三、reactive方法
用来创建一个响应式的数据对象,该API也很好地解决了Vue2通过 defineProperty
实现数据响应式的缺陷
<template><div id="app"><!-- 4. 访问响应式数据对象中的 count -->{{ state.count }}</div>
</template><script>
// 1. 从 vue 中导入 reactive
import {reactive} from 'vue'
export default {name: 'App',setup() {// 2. 创建响应式的数据对象const state = reactive({count: 3})// 3. 将响应式数据对象state return 出去,供template使用return {state}}
}
</script>
四、ref方法
1、简介
包装了一个响应式的数据对象,ref是通过 reactive
包装了一个对象,然后是将值传给该对象中的 value
属性
注意:.value是在访问ref方法才需要,在template模板是不需要的
2、使用
可以简单地把 ref(obj)
理解为这个样子 reactive({value: obj})
<script>
import {ref, reactive} from 'vue'
export default {name: 'App',setup() {const obj = {count: 3}const state1 = ref(obj)const state2 = reactive(obj)console.log(state1)console.log(state2)}}
</script>
3、ref与reactive
(1)基本类型值(string、number、boolean等)或单值对象(像{count:3}只有一个属性值的)使用ref
(2)引用类型值(object、array)使用reactive
4、获取标签元素或组件
(1)在Vue2中,我们获取元素都是通过给元素一个 ref
属性,然后通过 this.$refs.xx
来访问的,在Vue3中已经不再适用
(2)vue3获取元素如下
<template><div><div ref="el">div元素</div></div>
</template>
<script>
import {ref,onMounted} from 'vue'export default {name: "SetupView",setup() {// 创建一个DOM引用,名称必须与元素的ref属性名相同const el = ref(null)// 在挂载后才能通过el获取到目标元素onMounted(()=>{el.value.innerHTML = '内容被修改'})// 把创建的引用return出去return {el}},
};
</script>
(3)获取元素的操作步骤:
补充:设置的元素引用变量只有在组件挂载后才能访问到,因此在挂载前对元素进行操作都是无效的
五、toRef
1、简介
将某对象中的某值转化为响应式数据,其接收两个参数
(1)第一个参数为 obj
对象
(2)第二个参数为对象中的属性名
<template><div><div> {{ state }} </div></div>
</template><script>
import { toRef } from "vue";export default {name: "SetupView",setup() {const obj = { count: 3 };const state = toRef(obj, "count"); //注意:count有加单引号return { state };},
};
</script>
2、ref与toRef的区别
上面的例子ref也可以实现,那为什么还要toRef呢,来看看他们的区别吧
<template><div><p>{{ state1 }}</p><button @click="add1">增加1</button><p>{{ state2 }}</p><button @click="add2">增加2</button></div>
</template><script>
import { ref,toRef } from "vue";export default {name: "SetupView",setup() {const obj = {count:3}const state1 = ref(obj.count)const state2 = toRef(obj,'count')function add1(){state1.value++console.log('ref原始值:',obj);console.log('ref响应式',state1);}function add2(){state2.value++console.log('toRef原始值:',obj);console.log('toRef响应式',state2);}return {state1,state2,add1,add2}},
};
</script>
(1)ref是对传入数据的拷贝;toRef是对传入数据的引用
(2)ref值会改变更新视图;toRef值改变不会更新视图
六、toRefs
将传入的对象里所有的属性的值都转化为响应式数据对象,该函数支持一个参数,即 obj
对象
<template><div><div>{{ state }}</div></div>
</template><script>
import { toRefs } from "vue";export default {name: "SetupView",setup() {const obj={name:'前端学学学',age:18,gender:0}const state = toRefs(obj)console.log(state);},
};
</script>
七、shallowReactive 浅reactive
1、简介
shallowReactive传递给reactive的obj对象不止一层,那么每一次都会用Proxy包装
<template><div><div>{{ state }}</div></div>
</template><script>
import { reactive } from "vue";export default {name: "SetupView",setup() {const obj={a:1,first:{b:2,second:{c:3}}}const state = reactive(obj)console.log(state);console.log(state.first);console.log(state.first.second);},
};
</script>
如果一个对象层级比较深,那么每一层都用 Proxy
包装后,对于性能是非常不友好的
2、shallowreactived的浅reactive
shallowreactive只有第一层被Proxy处理了,即只有修改第一层的值,才会响应式更新
<template><div><div>{{ state.a }}</div><div>{{ state.first.b }}</div><div>{{ state.first.second.c }}</div><button @click="change1">改变1</button><button @click="change2">改变2</button></div>
</template><script>
import { shallowReactive } from "vue";export default {name: "SetupView",setup() {const obj={a:1,first:{b:2,second:{c:3}}}const state = shallowReactive(obj)function change1(){state.a = 7}function change2(){state.first.b = 8state.first.second.c =9console.log(state);}return {state,change1,change2}},
};
</script>
八、shallowRef
1、简介
浅层ref,一样是用来做性能优化的
(1)shallowReactive
是监听对象第一层的数据变化用于驱动视图更新
(2)shallowRef
则是监听 .value
的值的变化来更新视图的
(3)代码实例
<template><div><div>{{ state.a }}</div><div>{{ state.first.b }}</div><div>{{ state.first.second.c }}</div><button @click="change1">改变1</button><button @click="change2">改变2</button></div>
</template><script>
import { shallowRef } from "vue";export default {name: "SetupView",setup() {const obj={a:1,first:{b:2,second:{c:3}}}const state = shallowRef(obj)console.log(state);function change1(){state.value ={a:7,first:{b:8,second:{c:9}}}}function change2(){state.value.first.b = 4state.value.first.second.c = 5console.log(state);}return {state,change1,change2}},
};
</script>
①第二个按钮点击数据改变但是视图没变
②第一个按钮将整个 .value
重新赋值,视图才更新
2、triggerRef
triggerRef
可以解决上面实例的第二个按钮的问题,可以立马更新视图,其接收一个参数 state
,即需要更新的 ref
对象
<template><div><div>{{ state.a }}</div><div>{{ state.first.b }}</div><div>{{ state.first.second.c }}</div><button @click="change">改变</button></div>
</template><script>
import { shallowRef,triggerRef } from "vue";export default {name: "SetupView",setup() {const obj={a:1,first:{b:2,second:{c:3}}}const state = shallowRef(obj)console.log(state);function change(){state.value.first.b = 4state.value.first.second.c = 5triggerRef(state)console.log(state);}return {state,change}},
};
</script>
九、toRaw方法
toRaw
方法是用于获取 ref
或 reactive
对象的原始数据的
<template><div><div>{{ state.name }}</div><div>{{ state.age }}</div><button @click="change">改变</button></div>
</template><script>
import { reactive,toRaw } from "vue";export default {name: "SetupView",setup() {const obj={name:'前端学学学',age:18,}const state = reactive(obj)const raw = toRaw(state)function change(){state.age = 90console.log(obj);console.log(state);console.log(obj === raw);}return {state,change}},
};
</script>
上述代码就证明了 toRaw
方法从 reactive
对象中获取到的是原始数据,因此我们就可以很方便的通过修改原始数据的值而不更新视图来做一些性能优化了
注意: 补充一句,当 toRaw
方法接收的参数是 ref
对象时,需要加上 .value
才能获取到原始数据对象
十、markRaw
markRaw
方法可以将原始数据标记为非响应式的,即使用 ref
或 reactive
将其包装,仍无法实现数据响应式,其接收一个参数,即原始数据,并返回被标记后的数据
<template><div><div>{{ state.name }}</div><div>{{ state.age }}</div><button @click="change">改变</button></div>
</template><script>
import { reactive, markRaw } from "vue";export default {name: "SetupView",setup() {const obj = {name: "前端学学学",age: 18,};// 通过markRaw标记原始数据obj, 使其数据更新不再被追踪const raw = markRaw(obj);// 试图用reactive包装raw, 使其变成响应式数据const state = reactive(raw);function change() {state.age = 90;console.log(state);}return { state, change };},
};
</script>
被 markRaw
方法处理过后的数据不能被 reactive
包装成响应式数据,修改了值也不会更新视图了,即没有实现数据响应式
十一、provide && inject
1、简介
- provide :向子组件以及子孙组件传递数据。接收两个参数,第一个参数是
key
,即数据的名称;第二个参数为value
,即数据的值 - inject :接收父组件或祖先组件传递过来的数据。接收一个参数
key
,即父组件或祖先组件传递的数据名称
2、代码实例
假设这有三个组件,分别是 A.vue
、B.vue
、C.vue
,其中 B.vue
是 A.vue
的子组件,C.vue
是 B.vue
的子组件
// A.vue
<script>
import {provide} from 'vue'
export default {setup() {const obj= {name: '前端印象',age: 22}// 向子组件以及子孙组件传递名为info的数据provide('info', obj)}
}
</script>// B.vue
<script>
import {inject} from 'vue'
export default {setup() { // 接收A.vue传递过来的数据inject('info') // {name: '前端印象', age: 22}}
}
</script>// C.vue
<script>
import {inject} from 'vue'
export default {setup() { // 接收A.vue传递过来的数据inject('info') // {name: '前端印象', age: 22}}
}
</script>
十二、watch && watchEffect
watch
和 watchEffect
都是用来监视某项数据变化从而执行指定的操作的,但用法上还是有所区别
1、watch 简介
watch 格式:watch( source, cb, [options])
- source:可以是表达式或函数,用于指定监听的依赖对象
- cb:依赖对象变化后执行的回调函数
- options:可参数,可以配置的属性有 immediate(立即触发回调函数)、deep(深度监听)
(1)监听ref类型时:
<script>
import { ref, watch } from "vue";export default {name: "SetupView",setup() {const state = ref(0);watch(state, (newValue, oldValue) => {console.log(`原值${oldValue}`);console.log(`新值${newValue}`);});// 1秒后值+1setTimeout(() => {state.value++;}, 1000);},
};
</script>
(2)监听reactive类型时:
<script>
import { reactive, watch } from "vue";export default {name: "SetupView",setup() {const state = reactive({count:0});watch(()=>state.count,(newValue,oldValue)=>{console.log(`原值${oldValue}`);console.log(`新值${newValue}`);});// 1秒后值+1setTimeout(() => {state.count++;}, 1000);},
};
</script>
(3)当同时监听多个值时:
<script>
import { reactive, watch } from "vue";export default {name: "SetupView",setup() {const state = reactive({count:0,name:'23'});watch([()=>state.count,()=>state.name],([newCount,newName],[oldCount,oldName])=>{console.log(oldCount);console.log(newCount);console.log(oldName);console.log(newName);});// 1秒后值+1setTimeout(() => {state.count++;state.name = 'sxx'}, 1000);},
};
</script>
(4)因为 watch
方法的第一个参数我们已经指定了监听的对象,因此当组件初始化时,不会执行第二个参数中的回调函数,若我们想让其初始化时就先执行一遍,可以在第三个参数对象中设置 immediate: true
(5)watch
方法默认是渐层的监听我们指定的数据,例如如果监听的数据有多层嵌套,深层的数据变化不会触发监听的回调,若我们想要其对深层数据也进行监听,可以在第三个参数对象中设置 deep: true
(6)watch方法会返回一个stop方法,若想要停止监听,便可直接执行该stop函数
2、watchEffect
与 watch
的区别
(1)不需要手动传入依赖
(2)每次初始化时会执行一次回调函数来自动获取依赖
(3)无法获取到原值,只能得到变化后的值
<script>
import { reactive, watchEffect } from "vue";export default {name: "SetupView",setup() {const state = reactive({count:0,name:'23'});watchEffect(()=>{console.log(state.count);console.log(state.name);})// 1秒后值+1setTimeout(() => {state.count++;state.name = 'sxx'}, 1000);},
};
</script>
没有像 watch
方法一样先给其传入一个依赖,而是直接指定了一个回调函数
当组件初始化时,该回调函数会执行一次,自动获取到需要检测的数据
十三、getCurrentInstance
<template><div><div>{{ num }}</div></div>
</template>
<script>
import { ref,getCurrentInstance } from "vue";export default {name: "SetupView",setup() {const num = ref(3)const instance = getCurrentInstance()console.log(instance);return {num}},
};
</script>
1、输出值ctx
2、输出值proxy
ctx
和 proxy
的内容十分类似,只是后者相对于前者外部包装了一层 proxy
,由此可说明 proxy
是响应式的
十四、useStore
通过vuex中的useStore方法
// store 文件夹下的 index.js
import Vuex from 'vuex'const store = Vuex.createStore({state: {name: '前端印象',age: 22},mutations: {……},……
})// example.vue
<script>
// 从 vuex 中导入 useStore 方法
import {useStore} from 'vuex'
export default {setup() { // 获取 vuex 实例const store = useStore()console.log(store)}
}
</script>
相关文章:

vue3常用API之学习笔记
目录 一、setup函数 vue2与vue3变量区别 二、生命周期 三、reactive方法 四、ref方法 1、简介 2、使用 3、ref与reactive 4、获取标签元素或组件 五、toRef 1、简介 2、ref与toRef的区别 六、toRefs 七、shallowReactive 浅reactive 1、简介 2、shallowreactiv…...
Python 程序设计入门(005)—— 字符串操作
Python 程序设计入门(005)—— 字符串操作 目录 Python 程序设计入门(005)—— 字符串操作一、字符串切片与连接1、切片的索引方式2、切片操作的基本表达式3、 切片操作举例4、字符串连接 二、字符串替换:replace() 方…...

怎样将项目jar包放到服务器上
目录 1、在配置文件中配置账号密码 2.在父级的pom里面,加上这个标签 3. deploy部署 4. 注:这两个id得匹配上(原因:有的人会只有上传到测试包的权限,id对应,拥有账号密码的才能有权限) 5.子项…...

ruby调试
如果下载 ruby-debug-ide gem install ruby-debug-ide vscode 下载 ruby扩展 1, ruby 2,修改launch.json...

【云原生】使用kubeadm搭建K8S
目录 一、Kubeadm搭建K8S1.1环境准备1.2所有节点安装docker1.3所有节点安装kubeadm,kubelet和kubectl1.4部署K8S集群1.5所有节点部署网络插件flannel 二、部署 Dashboard 一、Kubeadm搭建K8S 1.1环境准备 服务器IP配置master(2C/4G,cpu核心…...

HCIE-Datacom真题和机构资料
通过认证验证的能力 具备坚实的企业网络跨场景融合解决方案理论知识,能够使用华为数通产品及解决方案进行企业园区网络、广域互联网络及广域承载网络的规划、建设、维护及优化,能够胜任企业网络全场景专家岗位(包括客户经理、项目经理、售前…...

轮足机器人硬件总结
简介 本文主要根据“轮腿机器人Hyun”总结的硬件部分。 轮腿机器人Hyun开源地址:https://github.com/HuGuoXuang/Hyun 1 电源部分 1.1 78M05 78M05是一款三端稳压器芯片,它可以将输入电压稳定输出为5V直流电压. 1.2 AMS1117-3.3 AMS1117-3.3是一种输…...

Flowable-网关-排他网关
目录 定义图形标记XML内容示例视频教程 定义 排他网关,也叫异或(XOR)网关,是 BPMN 中使用的最常见的网关之一,用来在流转中实 现发散分支决策。排他网关需要和条件顺序流搭配使用,当流程执行到排他网关&am…...
GET 和 POST 的区别
GET 和 POST 的区别(流利说) 从 http 协议的角度来说,GET 和 POST 它们都只是请求行中的第一个单词,除了语义不同,其实没有本质的区别。 之所以在实际开发中会产生各种区别,主要是因为浏览器的默认行为造成…...

FFmpeg中硬解码后深度学习模型的图像处理dnn_processing(一)
ffmpeg 硬件解码 ffmpeg硬件解码可以使用最新的vulkan来做,基本上来说,不挑操作系统是比较重要的,如果直接使用cuda也是非常好的选择。 AVPixelFormat sourcepf AV_PIX_FMT_NV12;// AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;AVPixelFormat d…...

计及需求响应和电能交互的多主体综合能源系统主从博弈优化调度策略(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
local-path-provisioner的使用(hostPath、local、local-path-provisioner三者对比)
前言 环境:k8s 1.22.17 、centos7.9 有时候,为了使用本地服务器上的磁盘存储资源,我们会使用hostPath这种方式来为k8s提供本地存储,本篇就来对比一下hostPath、local这两种使用本地服务器储存的方案,从而引出第三种lo…...

命令行快捷键Mac Iterm2
原文:Jump forwards, backwards and delete a word in iTerm2 on Mac OS iTerm2并不允许你使用 ⌥← 或 ⌥→ 来跳过单词。 你也不能使用 ⌥backspace 来删除整个单词。 下面是在Mac OS上如何配置iTerm2以便能做到这一点的方法。 退格键 首先,你需要将你的左侧 ⌥…...

无涯教程-Lua - Modules(模块)
模块就像可以使用 require 加载的库,并且具有包含Table的单个全局名称,该模块可以包含许多函数和变量。 Lua 模块 其中一些模块示例如下。 -- Assuming we have a module printFormatter -- Also printFormatter has a funtion simpleFormat(arg) -- …...

url重定向
不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。 如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话 就可能发生"跳错对象"的问题。 url跳转比较直接的危害是…...
Linux 查看IP地址、子网掩码和网关的配置信息
使用以下命令来查看IP地址、子网掩码和网关的配置信息: 1,使用ifconfig命令: ifconfig 在输出中,找到你正在使用的网络接口的配置信息。你将看到类似以下的内容: eth0: flags4163<UP,BROADCAST,RUNNING,MULTICA…...
token
token验证流程: ①客户端使用用户名和密码请求登录。 ②服务端收到请求,验证用户名和密码。 ③验证成功后,服务端会生成一个token,然后把这个token发送给客户端。 ④客户端收到token后把它存储起来,可以放在cookie…...

利用awk筛选给定时间范围内的日志
文章目录 筛选给定时间范围内的日志时间时间戳什么是时间戳? 系统时间 筛选日志时间示例简单示例mktime()函数是什么 进阶示例 筛选给定时间范围内的日志 时间 时间的表示方法: 时间戳系统时间(年月日时间) 时间戳 什么是时间…...
ORACLE字符集概念学习
1、字符集的一些基本知识 字符集有很多种,最初的字符集是ASCII,由于ASCII支持的字符很有限,因此随后又出现了很多的编码方案,这些编码方案大部分都是包括了ASCII 的。EBCDIC编码是另一个比较基本的编码,它的部分字符采…...

时间复杂度、空间复杂度实践练习(力扣OJ)
目录 文章目录 前言 题目一:轮转数组 思路一: 思路二: 思路三: 题目二:消失的数字 思路一: 思路二: 思路三: 题目三:移除元素 思路: 总结 前言 想要编写高效的…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...