代码编织梦想

文档:axios http://www.axios-js.com/

安装引入不赘述,我采用的全局引入

此处讲诉常用方法:

  • get:获取指定数据,一般用于查找
  • post:提交数据到指定区域,如上传,表单提交
  • delete:删除指定数据
  • put:更新
  • patch:局部更新

更多查看文档:

axios.request(config)

axios.get(url[, config])

axios.delete(url[, config])

axios.head(url[, config])

axios.options(url[, config])

axios.post(url[, data[, config]])

axios.put(url[, data[, config]])

axios.patch(url[, data[, config]])

请求配置:

{
   // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // default

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data, headers) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

   // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // default

   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default

   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },

   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5, // default

  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified, `socketPath` is used.
  socketPath: null, // default

  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}

响应体结构:

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},
 // 'request'
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}

 使用.then获取响应体信息:

axios.get('/user/12345')
  .then(function(response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  });

get

示例一:获取数据并且列表渲染

   <button @click="search">查询事件</button>         
          <ul>
            <li v-for="item in postList" :key="item.id" >
            {{ item.id }}{{ item.title }}{{ item.author }}
            </li>
          </ul> 

search() {
      axios.get("/data.json").then(res => {
        console.log(res);
        this.postList = res.data;//data才是返回的数据
        console.log(this.postList);
      },err=>{
        console.log(err)
});
    },

 示例二:请求格式类似于 http://localhost:8080/goods.json?id=1

 //请求格式类似于 http://localhost:8080/goods.json?id=1
this.$axios.get('/goods.json',{
    			params: {
                    id:1
                }
			}).then(res=>{
					console.log(res.data);
				},err=>{
					console.log(err);
			})

或者
this.$axios.get('/goods.json?id=1')
		  .then(res=>{
					console.log(res.data);
				},err=>{
					console.log(err);
			})

 或

this.$axios({
		method: 'get',
		url: '/goods.json',
    	params: {
            id:1
        }
	}).then(res=>{
		console.log(res.data);
	},err=>{
		console.log(err);
	})

post

示例一:新增一个postob对象

data(){
    return{
      postOb:{
        title:'',
        author:''//接受格式
      }
    }
  },    

add(){
      axios.post("/data.json",this.postOb).then(res=>{
        console.log(res)//传送数据postOb对象
        this.search();//刷新显示
      })
    },

示例二:

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(res=>{
    console.log(res);
  })
  ,err=> {
    console.log(err);
  });

或
$axios({
	method: 'post',
	url: '/url',
	data: {
		  firstName: 'Fred',
          lastName: 'Flintstone'
	}
}).then(res=>{
	console.log(res.data);
},err=>{
	console.log(err);
})

多个并发请求:

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // 两个请求现在都执行完成
  }));

async和await异步改造:

  • async作为一个关键字放在函数前面,表示该函数是一个异步函数。异步函数意味着该函数的执行不会阻塞后面代码的执行;返回一个promise对象。
  • 而 await 用于等待一个异步方法执行完成;
  • await 等待一个 Promise 对象,如果 Promise的状态变成了 resolve 或者 rejcet,那么 async函数会恢复执行。并会阻塞该函数内后面的代码。
  • 使用 async/await 可以实现用同步代码的风格来编写异步代码,这是因为 async/await 的基础技术使用了生成器Promise,生成器是协程的实现,利用生成器能实现生成器函数的暂停和恢复。

 async add1(){
       await axios.post("",this.postOb);
      this.search();
     
    }

put

this.$axios.put('/url',{
				id:1
			}).then(res=>{
				console.log(res.data);
			})

patch

this.$axios.patch('/url',{
				id:1
			}).then(res=>{
				console.log(res.data);
			})

delete

用于删除数据

get-params方式:params方式会将请求参数拼接在URL上

// 使用别名法
 
// 传参的2种形式,同get
 
1、params
axios
  .delete("/data.json", {
    params: {
      id: 12
    }
  })
  .then(res => {
    console.log(res, "delete");
  });
 
2、查询字符串形式,即参数拼接到url里
axios
  .delete("/data.json?id=2")
  .then(res => {
    console.log(res, "delete");
  });
 
  
// 不使用别名法 —————通过向axios传递的相关配置创建请求__axios(config)
let params = {
  id: 5
};
axios({
  method:'delete',
  url:'/data.json',
  params:params
}).then(res=>{
  console.log(res)
})

 参数以明文形式提交:

post-data方式:把axios.delete()中的params改为data,这样请求会把内容放入请求体里面

// 使用别名法
// data
axios
  .delete("/data.json", {
    data: {
      id: 5
    }
  })
  .then(res => {
    console.log(res);
  });
  
// 不使用别名法 ————通过传递相关配置创建请求
let data = {
  id: 5
};
axios({
  method:'delete',
  url:'/data.json',
  data:data
}).then(res=>{
  console.log(res)
})

参数以封装对象的形式提交-传送的数据作为data'对象

 axios实例的创建与配置

axios实例常用配置:

  •     baseURL 请求的域名,基本地址,类型:String
  •     timeout 请求超时时长,单位ms,默认:1000毫秒(ms),超过这个时长后端会报(返回)401超时。类型:Number
  •     url 请求路径,类型:String
  •     method 请求方法,如:get、post、put、patch、delete等。类型:String
  •     headers 设置请求头,类型:Object
  •     params 请求参数,将参数拼接在URL上,类型:Object
  •     data 请求参数,将参数放到请求体中,类型:Object

const instance = axios.create({

  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

示例一:

<template>
  <div class="hello">......</div>
</template>
 
<script>
import axios from "axios";
// 场景:如果后端接口地址有多个,并且超时时长不一样,此时我们可以我们可以创建axios实例,利用axios实例进行网络请求
export default {
  name: "HelloWorld",
  created() {
    // 创建axios实例1
    let instance = axios.create({
      baseURL: "http://loacalhost:8080",
      timeout: 1000,
    });
    instance.get("/data.json").then((res) => {
      console.log(res);
    });
    // 创建axios实例2  ————倘若有两个域名或设置超时时长不一样,我们可以再创建一个axios实例
    let instance2 = axios.create({
      baseURL: "http://loacalhost:8081",
      timeout: 2000,
    });
    instance2.get("/city.json").then((res) => {
      console.log(res);
    });
  },
};
</script>
<style scoped>
</style>

示例二:

let instance = axios.create({
  // 创建实例时设置配置默
  baseURL: "", //请求的域名/基本地址
  timeout: 2000, //请求的超时时长,单位毫秒,默认。
  url: "/data.json", //请求路径
  method: "get", //请求方法
  headers: {
    //设置请求头————我们可以给请求头添加一些参数
    token: "",
    post: {
       'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    }
  },
  params: { id: 5 }, //将请求参数拼接到url上
  data: { id: 5 }, //将请求参数放置到请求体里
});

全局配置:

全局配置:

//配置全局的超时时长
this.$axios.defaults.timeout = 2000;
//配置全局的基本URL
this.$axios.defaults.baseURL = 'http://localhost:8080';

实例配置:

let instance = this.$axios.create();
instance.defaults.timeout = 3000;

请求配置:

this.$axios.get('/goods.json',{
				timeout: 3000
			}).then()

配置会以一个优先顺序进行合并。优先级为:请求配置 > 实例配置 > 全局配置

// 使用由库提供的配置的默认值来创建实例
// 此时超时配置的默认值是 `0`
var instance = axios.create();

// 覆写库的超时默认值
// 现在,在超时前,所有请求都会等待 2.5 秒
instance.defaults.timeout = 2500;

// 为已知需要花费很长时间的请求覆写超时设置
instance.get('/longRequest', {
  timeout: 5000
});

拦截器

在请求或响应被 thencatch 处理前拦截它们。

请求拦截器:

this.$axios.interceptors.request.use(config=>{
				// 发生请求前的处理

				return config
			},err=>{
				// 请求错误处理

				return Promise.reject(err);
			})

响应拦截器:

axios.interceptors.response.use(res=> {
    // 对响应数据做点什么
    return res;
  }, err=>{
    // 对响应错误做点什么
    return Promise.reject(err);
  });

可以为自定义 axios 实例添加拦截器


//或者用axios实例创建拦截器,为自定义axios实例创建拦截器
let instance = $axios.create();
instance.interceptors.request.use(config=>{
    return config
})

取消拦截(eject)

let instance = this.$axios.interceptors.request.use(config=>{
				config.headers = {
					token: ''
				}
				return config
			})
			
//取消拦截
this.$axios.interceptors.request.eject(instance);

错误处理

不管是请求错误还是响应错误,都会执行catch方法

	// 请求拦截器
    axios.interceptors.request.use(
      config => {
        // 在发送请求前做些什么
        return config;
      },
      err => {
        // 在请求错误的时候的逻辑处理
        return Promise.reject(err);
      }
    );
 
    // 响应拦截器
    axios.interceptors.response.use(
      res => {
        // 在请求成功后的数据处理
        return res;
      },
      err => {
        // 在响应错误的时候的逻辑处理
        return Promise.reject(err);
      }
    ); 
 
	axios
      .get("/data.json")
      .then(res => {
        console.log(res);
      })
      .catch(err => {
        console.log(res);
      });

添加统一错误处理方法:

首先创建实例,给实例设置请求拦截器与响应拦截器。

(1)请求错误的常见状态码以4开头,如401-请求超时、404-接口未找到;

(2)响应错误的常见状态码以5开头,如500-服务器错误、502-服务器重启等。

(3)处理设置请求拦截器与响应拦截器的操作外,如果还要其他操作,我们可以在请求的时候,再使用catch方法。

    //  请求错误处理
    let instance = axios.create({});
    instance.interceptors.request.use(
      config => {//添加请求拦截器,在发送请求之前返回config
        return config;
      },
      err => {
        // 请求错误的常见状态码:4XX  401-请求超时  404-mot found
        $("#error").show();
        setTimeout(()=>{
           $("#error").hide(); 
        }, 2000)
        return Promise.reject(err);
      }
    );
 
    // 响应错误处理
    instance.interceptors.response.use(
      res => {//添加响应拦截器
        return res;
      },
      err => {
        // 响应错误的常见状态码 5XX 500-服务器错误 502-服务器重启
        $("#error").show();
        setTimeout(()=>{
           $("#error").hide(); 
        }, 2000)
        return Promise.reject(err);
      }
    );
    instance.get("/data.json").then(res=>{
        console.log(res,'请求成功')
    }).catch(err=>{
        console.log(err,'除了拦截器设置的处理之外的其他处理')
    })

 可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围

axios.get('/user/12345', {
  validateStatus: function (status) {
    return status < 500; // Reject only if the status code is greater than or equal to 500
  }
})

取消请求:

在查询数据的时候,很长时间(3-5s)仍未获取数据,这个时候需要取消请求。

<template>
  <div class="hello">取消请求</div>
</template>
 
<script>
import axios from "axios";
export default {
  name: "HelloWorld",
  created() {
    // 取消请求:用于取消正在进行的http请求(不常用,作为了解)
    let source = axios.CancelToken.source();
    axios
      .get("/data.json", {
        cancelToken: source.token,
      })
      .then((res) => {
        console.log(res);
      })
      .catch((err) => {//取消请求后会执行该方法
        console.log(err);
      });
 
    // 取消请求(其中,参数message是可选)该参数信息会发送到请求的catch中
    source.cancel("自定义的字符串可选");
  },
};
</script>
<style scoped>
</style>

实例封装

将网络请求单独抽离并封装为函数,进行网络请求的时候只需要调用对应的函数并且传入参数即可。这样将来即使需要更换请求库,也只需要对封装的函数进行修改而不是大量重构代码,可以大大减少工作量。

export function request(config) {
    // 1. 创建axios实例
    const instance = axios.create({
      baseURL: "http://localhost:8080",
      timeout: 5000,
    });
    // ​2. axios拦截器的使用
    // 2.1 添加请求拦截器
    /** 需要拦截请求的原因
     *   1.config中包含了某些不符合服务器要求的信息
     *   2.发送网络请求的时候需要向用户展示一些加载中的图标
     *   3.网站需要登录才能请求资源,也就是需要token才能请求资源
     */
    instance.interceptors.request.use(
      (config) => {
        // 在发送请求之前做些什么
        return config; //拦截器里一定要记得将拦截的结果处理后返回,否则无法进行数据获取
      },
      (err) => {
        // 对请求错误做些什么
        return Promise.reject(err); // 在请求错误的时候的逻辑处理
      }
    );
    // 2.2 添加响应拦截器
    instance.interceptors.response.use(
      (res) => {
        // 在请求成功后对响应数据做处理
        return res; // 对响应数据做点什么
      },
      (err) => {
        // 对响应错误做些什么
        return Promise.reject(err); // 在响应错误的时候的逻辑处理
      }
    );
    // 3. 发送网络请求
    //axios实例本身返回的就是Promise对象,直接调用即可
    return instance(config);
}

上述代码就是一个简单的request网络请求函数封装,这样每次调用其进行网络请求的时候创建的都是一个单独的axios实例,可以进行更加灵活的配置。

需要值得注意的地方就是拦截器,拦截器会对请求和响应的结果进行一定的处理,不过配置拦截器后一定要记得将拦截的结果在最后放行。 

登录权限

需要token的接口实例

    // 需要token的接口
    let instance = axios.create({});
    instance.interceptors.request.use(config=>{
        config.headers.token = '';
     //这种写法会覆盖掉headers中的其他参数,导致headers中只包含token这一个参数,所以不建议这种写法
     // config.headers = {
     //       token: ''
     // }
        return config
    }, err => {
      return Promise.reject(err);
    })

不需要token的接口实例

    // 不需要token接口
    let newInstance = axios.create({});

移动端开发数据加载loading动画

实现的效果是请求数据的时候显示loading动画,数据响应后隐藏loading动画。

    // 请求时加载loading动画
    let instance_phone = axios.create({});
    instance_phone.interceptors.request.use(config=>{
        $('#loading').show();
        return config
    }, err => {
      return Promise.reject(err);
    })
 
    instance_phone.interceptors.response.use(res=>{
        $('#loading').hide();
        return res
    }, err => {
      return Promise.reject(err);
    })

参考:

Axios使用方法详解,从入门到进阶-CSDN博客

Axios 中文文档 | Axios 中文网

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_59746686/article/details/136389882

axios学习笔记_xsrfcookiename-爱代码爱编程

Axios学习结构 ​ Axios学习网址:起步 | Axios 中文文档 | Axios 中文网 (axios-http.cn) 1. Axios简介与特征 Axios简介  Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 该框架主要就是用来请求HTTP接口的,底层就是传说中的Ajax。 ​

在做题中学习(54):点名-爱代码爱编程

LCR 173. 点名 - 力扣(LeetCode) 此题有不同的几种解法: 解法一:暴力枚举  O(n); 解法二:哈希表       把原数组丢入哈希表,遍历哈希表,看看哪个数值为0即可。 O(n)空间+O(n)时间 解法三:位运算       搞一个和原数组大小相同的数组,和原数组进行异或,最后看看剩下是哪一个数即可。         

rustgui学习(iced)之小部件(十):如何使用tooltip部件来制作文字提示?-爱代码爱编程

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1

【hcip学习】bgp对等体组、聚合、路由反射器、联盟、团体属性-爱代码爱编程

一、大规模BGP网络所遇到的问题 BGP对等体众多,配置繁琐,维护管理难度大 BGP路由表庞大,对设备性能提出挑战 IBGP全连接,应用和管理BGP难度增加,邻居数量过多 路由变化频繁,导致路由更新频繁 二、解决大规模BGP网络所遇到的问题 1、BGP对等体众多 对等体组(Peer Group) BGP团体(Community

牛客网java实战项目-爱代码爱编程

仿牛客网社区的学习笔记 1. 项目环境搭建1.1 开发社区首页 2.开发社区登录模块2.1 发送邮件2.2 开发注册功能2.3 会话管理2.4 生成验证码2.5 开发登录、退出功能2.6 显示登录信息

ego_planner学习-爱代码爱编程

飞行类型 enum TARGET_TYPE     {       MANUAL_TARGET = 1,       PRESET_TARGET = 2,       REFENCE_PATH = 3     }; target_type_ == TARGET_TYPE::PRESET_TARGET)       trigger_sub

来学习线程啦-爱代码爱编程

线程的相关概念 程序 简单点说:程序就是我们写的代码;也可以理解为:为完成特定任务,用某种语言编写的一组指令的集合 进程 进程是指运行中的程序。 比如:我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间

使用多实例学习进行乳腺癌组织病理学图像分类和定位-爱代码爱编程

计算机辅助病理学分析显微组织病理学图像以诊断越来越多的乳腺癌患者,可以降低诊断成本和延迟。组织病理学中的深度学习在过去十年中因其在分类和定位任务中实现最先进的性能而引起了人们的关注。卷积神经网络是一种深度学习框架,在组织图像分析方面提供了显着的结果,但缺乏提供决策背后的解释和推理。 我们的目标是通过提供显微组织病理学图像的定位来更好地解释分类结果。将图像

【声呐仿真】学习记录3.5-爱代码爱编程

【声呐仿真】学习记录3.5-docker中Gazebo是否使用GPU?解决声呐图像黑屏 🤡打包镜像,重装驱动(失败)Xorg重新配置DAVE环境(补充之前教程中的一些细节)解决声呐图像黑屏问题 在容器

axios学习-爱代码爱编程

一、了解axios 1. axios 是什么 axios 是基于Promise 的HTTP客户端,可以在浏览器和node 环境中运行; 在浏览器中发送ajax请求,在node 中发送http请求 特点 在浏

学习古琴律学的好东西,帮您从基因里学古琴-爱代码爱编程

《从基因里学懂古琴》是一本关于古琴律学的著作,作者通过基因的角度来解读古琴音乐的奥秘和美妙。古琴作为我国传统文化的瑰宝之一,具有悠久的历史和独特的音乐风格,但其律学原理一直以来都是一个谜。本书从基因的角度探讨了古琴音乐的律学特点。作者通过研究琴家的基因组,发现了一些与古琴演奏技巧和音乐感知能力相关的基因。他认为这些基因的存在与发展,对古琴音乐的传承和演

c++_容器常用算法_学习笔记-爱代码爱编程

常用头文件: #include<algorithm> #include<numeric> #include<functional> 1 遍历 1.1 for_each遍历容器 f