Vue.js中的8种组件间的通信方式;3个组件实例是前6种通信的实例,组件直接复制粘贴即可看到运行结果

文章目录

        • 一、$children / $parent
        • 二、props / $emit
        • 三、eventBus
        • 四、ref
        • 五、provide / reject
        • 六、$attrs / $listeners
        • 七、localStorage / sessionStorage
        • 八、Vuex

实例以element ui为例。例子从上往下逐渐变复杂(后面例子没有删前面的无用代码,有时间重新整理一下!)

一、$children / $parent

在这里插入图片描述

  • 拿到 $children / $parent 即可访问子 / 父 组件的所有变量和方法。
  • 官方说 $children / $parent 仅作为应急的通信方法,其中一个原因就是 $children / $parent仅代表的是根组件下的第一个子/父vue组件(普通html标签不含有vue实例,不包含在内),当位置变化或者之间需要增加新的组件,对应的指向就变了,如以下例子。
  • 一般用在组件简单且不易改变的情形,单独把子组件放在根组件的下一级。
  • 使用实例(复制粘贴即可跑起来看效果):
// 子组件
// 1.创建子组件
<template><div><!-- 注意:template中没有this,这里没有this,即不用this.parentMsg -->我是子组件,父组件的数据:{{parentMsg}}</div>
</template><script>
export default {data() {return {msg: "children",parentMsg:""};},mounted(){console.log(this.$parent)this.parentMsg = this.$parent.msg}
};
</script><style scoped>
</style>
// 父组件
<template><!-- 4.使用 --><div><div class="main">我是父组件,子组件的数据:{{childrenMsg}}</div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><p-com></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: ""};},mounted() {console.log(this.$children)this.childrenMsg = this.$children[0].msg;}
};
</script><style scoped>
</style>

两个vue文件放在同一目录下即可运行。
中间需要间插入el组件时,父子关系变为子孙,获取数据失败:

// 父组件模板改为此
<template><!-- 4.使用 --><div><div class="main">我是父组件,子组件的数据:{{childrenMsg}}</div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><el-card><p-com></p-com></el-card></div>
</template>

然而插入非element组件(即html标签),则父子关系不变:

// 父组件模板改为此
<template><!-- 4.使用 --><div><div class="main">我是父组件,子组件的数据:{{childrenMsg}}</div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><div><p-com></p-com></div></div>
</template>

二、props / $emit

官方推荐的父子关系通信方式,不用在乎层级关系,而且没有多余数据传输,父组件给什么,子组件就拿什么、用什么。(原理也是监听和广播,后第三种方式一样,只不过这是局部的,别忘了@是v-on的省略)。props应该也可以放函数地址然后子组件调用,如果可以的话也可以替代emit(待测)。
父组件:

<template><!-- 4.使用 --><div>父组件:<div class="main">我是父组件,我自己拿的子组件数据:{{childrenMsg}}<el-button type="text" @click="alertBox(true)">点我出弹框</el-button><br />子组件主动给我更新的数据:{{childrenMsg2}}</div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><br />子组件:<p-com:parentMsg2="msg"memo="这是爸爸传给你的字符串"@alertBox="flag=>{alertBox(flag)}"@setParentMsg="msg=>{setMsg(msg)}"></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: "",childrenMsg2: ""};},methods: {alertBox(flag) {alert(`调用了${flag ? "自己" : "爸爸"}的弹框`);},setMsg(msg) {this.childrenMsg2 = msg;}},mounted() {console.log(this.$children);this.childrenMsg = this.$children[1].msg;}
};
</script><style scoped>
</style>

子组件:

<template><div><!-- 注意:template中没有this,这里没有this,即不用this.parentMsg -->我是子组件,我自己拿的父组件数据:{{parentMsg}}<br />爸爸用props传给我的信息:{{parentMsg2}}(备注:{{memo}}<el-button type="text" @click="useParentMethods">点我出弹框,并且修改爸爸的数据</el-button></div>
</template><script>
export default {props: ["parentMsg2", "memo"],data() {return {msg: "children",parentMsg: ""};},methods: {useParentMethods() {this.$emit("alertBox", false);this.$emit("setParentMsg", `看你还嚣张! ${Date().split(' ')[4]}`);}},mounted() {console.log(this.$parent);this.parentMsg = this.$parent.msg;}
};
</script><style scoped>
</style>

三、eventBus

监听和广播:
优点:使用简单,导入即用。
缺点:阅读性差,因为你只能打印出这个bus(vue实例),看到所有的监听事件,但并不知道事件谁用了,在哪用的,用来干什么,所以仅适合小规模开发,非父子组件交互较少场景,仅用来处理非父子组件间的通信。
使用:
1.封装一个bus
model下新建eventBus.js(一般是这个目录)
在这里插入图片描述
内容

import Vue from 'vue'var EmitData =  new Vue();
export default EmitData; // 暴露一个vue实例,统一监听、广播所有事件

2.父组件导入并且监听(非父子组件也如此)

<template><!-- 4.使用 --><div>父组件:<div class="main">我是父组件,我自己拿的子组件数据:{{childrenMsg}}<el-button type="text" @click="alertBox(true)">点我出弹框</el-button><br />子组件主动给我更新的数据:{{childrenMsg2}}<div>广播更新时间:{{time}}</div></div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><br />子组件:<p-com:parentMsg2="msg"memo="这是爸爸传给你的字符串"@alertBox="flag=>{alertBox(flag)}"@setParentMsg="msg=>{setMsg(msg)}"></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";
import eventBus from "@/model/eventBus.js";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: "",childrenMsg2: "",time: ""};},methods: {alertBox(flag) {alert(`调用了${flag ? "自己" : "爸爸"}的弹框`);},setMsg(msg) {this.childrenMsg2 = msg;}},mounted() {console.log(this.$children);this.childrenMsg = this.$children[1].msg;eventBus.$on("updateTime", time => {this.time = time;});}
};
</script><style scoped>
</style>

3.子组件导入并且广播(触发事件)(非父子组件也如此)

<template><div><!-- 注意:template中没有this,这里没有this,即不用this.parentMsg -->我是子组件,我自己拿的父组件数据:{{parentMsg}}<br />爸爸用props传给我的信息:{{parentMsg2}}(备注:{{memo}}<el-button type="text" @click="useParentMethods">点我出弹框,并且修改爸爸的数据</el-button><el-button @click="updateParentTime">点我更新时间</el-button></div>
</template><script>
import eventBus from "@/model/eventBus.js";export default {props: ["parentMsg2", "memo"],data() {return {msg: "children",parentMsg: ""};},methods: {useParentMethods() {this.$emit("alertBox", false);this.$emit("setParentMsg", `看你还嚣张! ${Date().split(' ')[4]}`);},updateParentTime(){eventBus.$emit("updateTime",Date().split(' ')[4])}},mounted() {console.log(this.$parent);this.parentMsg = this.$parent.msg;}
};
</script><style scoped>
</style>

移除监听:

eventBus.$off('updateTime', {}) 

四、ref

如果在普通的 DOM 元素上使用ref,引用指向的就是 DOM 元素;如果用在element组件上,引用就指向组件vue实例,可以通过实例直接调用组件的方法、数据或 DOM 元素。
所以ref是单向的,父操作子的数据和方法。
使用:
给子组件注入ref=“xx”,之后xx就是这个子组件的实例了(在this.$refs.xx调用时要注意他是最后加载的,一般为了确保加载完成可以使用setTimeout或者this.$nextTick(()=>{this.$refs.xx}))
子组件不用变,父组件增加ref

<template><!-- 4.使用 --><div>父组件:<div class="main">我是父组件,我自己拿的子组件数据:{{childrenMsg}}<el-button type="text" @click="alertBox(true)">点我出弹框</el-button><br />子组件主动给我更新的数据:{{childrenMsg2}}<div>广播更新时间:{{time}}</div><el-button @click="getChild()">点我使用refs拿子组件数据和方法</el-button></div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><br />子组件:<p-com:parentMsg2="msg"memo="这是爸爸传给你的字符串"@alertBox="flag=>{alertBox(flag)}"@setParentMsg="msg=>{setMsg(msg)}"ref="pCom"></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";
import eventBus from "@/model/eventBus.js";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: "",childrenMsg2: "",time: ""};},methods: {alertBox(flag) {alert(`调用了${flag ? "自己" : "爸爸"}的弹框`);},setMsg(msg) {this.childrenMsg2 = msg;},getChild(){alert("子组件msg:"+this.$refs.pCom.msg+" ;并且更新自己的时间")this.$refs.pCom.updateParentTime()}},mounted() {console.log(this.$children);this.childrenMsg = this.$children[1].msg;eventBus.$on("updateTime", time => {this.time = time;});}
};
</script><style scoped>
</style>

五、provide / reject

provide/ inject 是vue2.2.0新增的api,在组件多层嵌套的时候,根组件只要通过provide来提供变量, 然后任意子组件(孙组件、重孙等等)中通过inject来注入变量(注入this中)即可拿到根组件数据、方法。不局限于只能从当前父组件的props属性中获取数据、方法。由此可知,provide / reject是单向的,只提供子孙等组件获取根组件数据、方法。
父组件:

<template><!-- 4.使用 --><div>父组件:<div class="main">我是父组件,我自己拿的子组件数据:{{childrenMsg}}<el-button type="text" @click="alertBox(true)">点我出弹框</el-button><br />子组件主动给我更新的数据:{{childrenMsg2}}<div>广播更新时间:{{time}}</div><el-button @click="getChild()">点我使用refs拿子组件数据和方法</el-button></div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><br />子组件:<p-com:parentMsg2="msg"memo="这是爸爸传给你的字符串"@alertBox="flag=>{alertBox(flag)}"@setParentMsg="msg=>{setMsg(msg)}"ref="pCom"></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";
import eventBus from "@/model/eventBus.js";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: "",childrenMsg2: "",time: ""};},provide() {return {rootMsg: this.msg,rootAlertBox: this.alertBox};},methods: {alertBox(flag) {alert(`调用了${flag ? "自己" : "爸爸"}的弹框`);},setMsg(msg) {this.childrenMsg2 = msg;},getChild() {alert("子组件msg:" + this.$refs.pCom.msg + " ;并且更新自己的时间");this.$refs.pCom.updateParentTime();}},mounted() {console.log(this.$children);this.childrenMsg = this.$children[1].msg;eventBus.$on("updateTime", time => {this.time = time;});}
};
</script><style scoped>
</style>

子组件:

<template><div><!-- 注意:template中没有this,这里没有this,即不用this.parentMsg -->我是子组件,我自己拿的父组件数据:{{parentMsg}}<br />爸爸用props传给我的信息:{{parentMsg2}}(备注:{{memo}}<el-button type="text" @click="useParentMethods">点我出弹框,并且修改爸爸的数据</el-button><el-button @click="updateParentTime">点我更新时间</el-button><el-button @click="userPJ()">点我看看provide / reject有没有获取到</el-button></div>
</template><script>
import eventBus from "@/model/eventBus.js";export default {props: ["parentMsg2", "memo"],data() {return {msg: "children",parentMsg: ""};},inject: {rootMsg: { default: "获取根组件数据失败" },rootAlertBox: {default: () => {return "获取根组件函数失败";}}},methods: {useParentMethods() {this.$emit("alertBox", false);this.$emit("setParentMsg", `看你还嚣张! ${Date().split(" ")[4]}`);},updateParentTime() {eventBus.$emit("updateTime", Date().split(" ")[4]);},userPJ(){alert(this.rootMsg)this.rootAlertBox()}},mounted() {console.log(this.$parent);this.parentMsg = this.$parent.msg;}
};
</script><style scoped>
</style>

六、$attrs / $listeners

在vue2.4中,引入了$attrs 和$listeners , 新增了inheritAttrs 选项。

inheritAttrs:默认值true,继承所有的父组件属性(除props的特定绑定)作为普通的HTML特性应用在子组件的根元素上,如果你不希望组件的根元素继承特性设置inheritAttrs: false,但是class属性会继承(简单的说,inheritAttrs:true 继承除props之外的所有属性;inheritAttrs:false 只继承class属性)

$attrs–继承所有的父组件属性(除了prop传递的属性、class 和 style ),一般用在子组件的子元素上,如第一个例子的

$listeners–属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)
实现:

1.同级创建pCom的子组件ppCom

<template><el-button @click="runGrand()">点我调用 attrs / listeners</el-button>
</template>
<script>
export default {methods: {runGrand() {alert(this.$attrs.noProp);this.$listeners.alertBox(false);}},mounted() {console.log(this.$attrs);console.log(this.$listeners);}
};
</script>

2.pCom

<template><div><!-- 注意:template中没有this,这里没有this,即不用this.parentMsg -->我是子组件,我自己拿的父组件数据:{{parentMsg}}<br />爸爸用props传给我的信息:{{parentMsg2}}(备注:{{memo}}<el-button type="text" @click="useParentMethods">点我出弹框,并且修改爸爸的数据</el-button><el-button @click="updateParentTime">点我更新时间</el-button><el-button @click="userPJ()">点我看看provide / reject有没有获取到</el-button><!-- attrs:在模板外需要用this.$attrs获取,他包含了父组件的所有数据listeners:在模板外需要用this.$listeners获取,他包含了父组件的所有事件(监听)inheritAttrs - 默认true:inheritAttrs:true 子标签继承除props之外的所有特性;inheritAttrs:false 只继承class属性传给下一级,注入到他的this--><br />pCom的子组件:<my-ppcom v-bind="$attrs" v-on="$listeners" ></my-ppcom></div>
</template><script>
import eventBus from "@/model/eventBus.js";
import ppCom from "./ppCom"export default {props: ["parentMsg2", "memo"],components:{"my-ppcom":ppCom},data() {return {msg: "children",parentMsg: ""};},inject: {rootMsg: { default: "获取根组件数据失败" },rootAlertBox: {default: () => {return "获取根组件函数失败";}}},methods: {useParentMethods() {this.$emit("alertBox", false);this.$emit("setParentMsg", `看你还嚣张! ${Date().split(" ")[4]}`);},updateParentTime() {eventBus.$emit("updateTime", Date().split(" ")[4]);},userPJ(){alert(this.rootMsg)this.rootAlertBox()}},mounted() {console.log(this.$parent);this.parentMsg = this.$parent.msg;}
};
</script><style scoped>
</style>

3.父组件

<template><!-- 4.使用 --><div>父组件:<div class="main">我是父组件,我自己拿的子组件数据:{{childrenMsg}}<el-button type="text" @click="alertBox(true)">点我出弹框</el-button><br />子组件主动给我更新的数据:{{childrenMsg2}}<div>广播更新时间:{{time}}</div><el-button @click="getChild()">点我使用refs拿子组件数据和方法</el-button></div><!-- 单独放在根组件的下一级,保证层级关系不被影响 --><br />子组件:<p-com:parentMsg2="msg"memo="这是爸爸传给你的字符串"@alertBox="flag=>{alertBox(flag)}"@setParentMsg="msg=>{setMsg(msg)}"ref="pCom"noProp="子组件不要prop接受我,这是给孙组件的字符串"></p-com></div>
</template><script>
// 2.引入
import pCom from "./pCom";
import eventBus from "@/model/eventBus.js";export default {components: { pCom }, // 3.挂载data() {return {msg: "parent",childrenMsg: "",childrenMsg2: "",time: ""};},provide() {return {rootMsg: this.msg,rootAlertBox: this.alertBox};},methods: {alertBox(flag) {alert(`调用了${flag ? "自己" : "爸爸"}的弹框`);},setMsg(msg) {this.childrenMsg2 = msg;},getChild() {alert("子组件msg:" + this.$refs.pCom.msg + " ;并且更新自己的时间");this.$refs.pCom.updateParentTime();}},mounted() {console.log(this.$children);this.childrenMsg = this.$children[1].msg;eventBus.$on("updateTime", time => {this.time = time;});}
};
</script><style scoped>
</style>

七、localStorage / sessionStorage

通信比较简单,数据和状态比较混乱,不太容易维护。
localStorage 将数据存入浏览器,关闭浏览器再次打开仍然存在,需要手动清除;
sessionStorage将数据存在对话框,关闭这个页面就没了。
他们的操作几乎是一样的,也都是js内置方法,也可以自己封装以下(我的另一篇博客有封装localStorage vue项目将token存在(vuex)store和localstorage中)。使用原生的话注意每次存入要JSON格式化,拿出要JSON解析。

localStorage 使用:

在任何地方使用 localStorage.setItem("k", JSON.stringify("v"))存入数据(方法-函数地址);
在任何地方使用 JSON.parse(localStorage.getItem("k")) 读取数据(方法-函数地址);
任何地方包括vue实例以外,因为他是原生js。

八、Vuex

数据状态管理器,适用于数据复杂、交互频繁场景,选择时要在不使用vue的困难和使用vuex的繁琐中权衡,当然啦,不管用不用都应该拿个例子来学,见我的另一篇博客
Vue使用Vuex一步步封装并使用store

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

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

相关文章

不可思议的混合模式 background-blend-mode

本文接前文&#xff1a;不可思议的混合模式 mix-blend-mode 。由于 mix-blend-mode 这个属性的强大&#xff0c;很多应用场景和动效的制作不断完善和被发掘出来&#xff0c;遂另起一文继续介绍一些使用 mix-blend-mode 制作的酷炫动画。 CSS3 新增了一个很有意思的属性 -- mix-…

如何更改从Outlook发送的电子邮件中的“答复”地址

If you’re sending an email on behalf of someone else, you might want people to reply to that person instead of you. Microsoft Outlook gives you the option to choose a different default Reply address to cover this situation. 如果您要代表其他人发送电子邮件&…

在Windows 7或Vista资源管理器中禁用缩略图预览

If you want to speed up browsing around in explorer, you might think about disabling thumbnail previews in folders. 如果要加快在资源管理器中的浏览速度&#xff0c;可以考虑禁用文件夹中的缩略图预览。 Note that this works in Windows 7 or Vista 请注意&#xf…

mysql 表数据转储_在MySQL中仅将表结构转储到文件中

mysql 表数据转储For this exercise, we will use the mysqldump utility the same as if we were backing up the entire database. 在本练习中&#xff0c;我们将像备份整个数据库一样使用mysqldump实用程序。 Syntax: 句法&#xff1a; mysqldump -d -h localhost -u root -…

lenos快速开发脚手架

2019独角兽企业重金招聘Python工程师标准>>> lenos一款快速开发模块化脚手架&#xff0c; lenos(p为spring boot版本扩展名)一款快速开发模块化脚手架&#xff0c;采用spring bootspringSpringMvcmybatisshiroswaggerehcachequartzfreemarkerlayui技术开发&#xff…

火狐ok谷歌适配_“ OK Google”在锁定手机上的安全性越来越高

火狐ok谷歌适配If you use “OK Google” to invoke the Assistant on your phone, things are about to change. Google is removing the “Unlock with Voice Match” feature, so the Assistant is going to get a lot more secure. 如果您使用“确定Google”在手机上调用助…

angular ng-zorro 用组件自身方的法来重置表单校验

官网文档的API并没有提供对应的重置表单校验函数の说明&#xff0c;在控制台打印this.validateForm&#xff08;校验表单对象&#xff09; 往往我们只关注亮色函数、属性&#xff0c;而这次重置函数藏在__prop__中&#xff01; 激动万分的使用 this.validateForm.reset()&…

Django用户注册、登录、注销(一)

使用Django自带的用户认证系统编写认证、登录、注销基本功能 功能&#xff1a; 使用Django默认的User表 1&#xff09;注册 判断是否已存在此用户&#xff0c;存在的话提示报错“用户已存在”&#xff1b; 判断两次输入的密码是否一致&#xff0c;不一致的话提示报错“密码不一…

如何在PowerPoint中自动调整图片大小

PowerPoint can automatically resize an image to fit a shape. You can also resize multiple images already in your presentation to all be the same size. Here’s how it works. PowerPoint可以自动调整图像大小以适合形状。 您还可以将演示文稿中已有的多个图像调整为…

如何在不支付Adobe Photoshop费用的情况下处理Camera Raw

You might think that you need expensive software to take advantage of Camera RAW—something like Photoshop or the more modestly priced Lightroom. Fortunately there is freeware that can help you achieve professional results without professional costs. 您可能…

eclipse 代码提示后面的百分比是什么意思?

简而言之&#xff0c;就是提示你其他人&#xff08;开发人员&#xff09;在此情形下使用该方法百分比&#xff0c;最常用方法百分比 见http://www.eclipse.org/recommenders/manual/#d0e32 Call Completion The Call Completion engine, for example, provides you with recomm…

travis-cli 使用

1. 添加项目登录 travis 选择对应项目即可 2. 添加持续集成文件.travis.ymllanguage: node_js node_js:- "node" before_install: - npm install -g jspm - jspm install script: - jspm bundle lib/main --inject备注&#xff1a;这是一个jspm 项目 3. 构建travis 是…

在Windows Media Center中收听超过100,000个广播电台

A cool feature in Windows 7 Media Center is the ability to listen to local FM radio. But what if you don’t have a tuner card that supports a connected radio antenna? The RadioTime plugin solves the problem by allowing access to thousands of online radio …

IntelliJ IDEA——数据库集成工具(Database)的使用

idea集成了一个数据库管理工具&#xff0c;可以可视化管理很多种类的数据库&#xff0c;意外的十分方便又好用。这里以oracle为例配置。 1、配置 在窗口的右边有个Database按钮&#xff0c;点击。 如果没有&#xff0c;请点击上方的View(视图)-Tool Windows(工具窗口)-Database…

代码评审会议_如何将电话会议(和访问代码)另存为联系人

代码评审会议Dialing a conference call doesn’t have to be a tedious process. Your iPhone or Android phone can automatically dial into the call and enter a confirmation code for you. You just have to create a special type of contact. 拨打电话会议不一定是一个…

使用iOS 4越狱iPhone或iPod Touch

In case you haven’t heard the news over the past couple of days, there is now an incredibly easy way to jailbreak your iPod Touch or iPhone running iOS 4. Here we will take a look at how easy the process is. 如果您在过去的几天里没有听到这个消息&#xff0c…

在Windows 7中禁用或修改Aero Peek的“延迟时间”

Are you looking for an easy way to modify the “delay time” for Aero Peek in Windows 7 or perhaps want to disable the feature altogether? Then see how simple it is to do either with the Desktop Peek Tweak. 您是否正在寻找一种简便的方法来修改Windows 7中Aer…

音频剪切_音频编辑入门指南:剪切,修剪和排列

音频剪切Audacity novices often start with lofty project ideas, but sometimes they lack the basics. Knowing how to cut and trim tracks is basic audio editing and is a fundamental starting point for making more elaborate arrangements. 大胆的新手通常从崇高的项…

搭建spring boot环境并测试一个controller

Idea搭建spring boot环境一、新建项目二、起步依赖三、编写SpringBoot引导类四、编写Controller五、热部署一、新建项目 1.新建project 2.选择SpringInitializr&#xff0c;选择jdk&#xff0c;没有则需要下载并配置(若选择Maven工程则需要自己添加pom.xml所需依赖坐标和Java…

音频噪声抑制_音频编辑入门指南:基本噪声消除

音频噪声抑制Laying down some vocals? Starting your own podcast? Here’s how to remove noise from a messy audio track in Audacity quickly and easily. 放下人声&#xff1f; 开始自己的播客&#xff1f; 这是在Audacity中快速轻松地消除杂乱音轨中噪声的方法。 Th…