javascript学习第一章
1.1 类型、对象,简单使用:
定义对象
var book = { topic: "JavaScript", fat: true };
读取对象
book.topic book["fat]
赋值
book.author = "Flanagan" book.contents = {};
定义数组
var primes = [2,3,5,7]
读取数组
primes[0]
数组中元素替换
primes[4] = 9;
定义多级数组
var points = [ {x:0,y:0}, {x:1,y:1} ];
对象中有数组
var data = { trial1:[[1,2],[3,4]], trial1:[[2,3],[4,5]] };
读取
data.trial1[0][1]
定义函数
function plus1(x){ return x+1; }
调用函数
plus1(y)
定义构造函数初始化 Point 对象
function Point(x,y){ this.x = x; this.y = y; }
使用 new 创建实例
var p = new Point(1,1);
使用构造函数的 prototype 对象赋值给 Point 对象定义方法
Point.prototype.r = function(){ return Math.sqrt(this.x * this.x + this.y * this.y);};
调用方法
p.r()
1.2 写个贷款计算器
1.2.1 前端代码
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Loan Calculator</title>
<style>
.output {
font-weight: bold;
#payment {
text-decoration: underline;
}
#graph {
border: solid black 1px;
}
th,
td {
vertical-align: top;
}
}
</style>
</head>
<body>
<table>
<tr>
<th>Enter Loan Data:</th>
<td></td>
<th>Loan Balance,Cumulative Equity,and Interest PayMents</th>
</tr>
<tr>
<td>Amount of the loan ($):</td>
<td><input id="amount" onchange="calculate();" /></td>
<td rowspan="8">
<canvas id="graph" width="400" height="250"></canvas>
</td>
</tr>
<tr>
<td>Annual interest(%):</td>
<td><input id="apr" onchange="calculate();" /></td>
</tr>
<tr>
<td>Repayment period(years):</td>
<td><input id="years" onchange="calculate();" /></td>
</tr>
<tr>
<td>Zipcode(to fnd lenders):</td>
<td><input id="zipcode" onchange="calculate();" /></td>
</tr>
<tr>
<th>Approximate Payments:</th>
<td><button onclick="calculate();">Calculate</button></td>
</tr>
<tr>
<td>Monthly payment:</td>
<td>$<span class="output" id="payment"></span></td>
</tr>
<tr>
<td>Total payment:</td>
<td>$<span class="output" id="total"></span></td>
</tr>
<tr>
<td>Total interest:</td>
<td>$<span class="output" id="totalinterest"></span></td>
</tr>
<tr>
<th>Sponsors:</th>
<td colspan="2">
Apply for your loan with one of these fne lenders:
<div id="lenders"></div>
</td>
</tr>
</table>
<script>
'use script'; //如果浏览器支持开启ECMAScript 5严格模式
/**这里的脚本定义了caculate()函数,在HTML代码中绑定事件处理程序时会调用它丰这个函数从<input>元素中读取数据,计算贷款赔付信息,并将结果显示在<span>元素中*同样,这里还保存了用户数据、展示了放贷人链接并绘制出了图表*/
function calculate() {
//查找文档中用于输入输出的元素
var amount = document.getElementById('amount');
var apr = document.getElementById('apr');
var years = document.getElementById('years');
var zipcode = document.getElementById('zipcode');
var payment = document.getElementById('payment');
var total = document.getElementById('total');
var totalinterest = document.getElementById('totalinterest');
//假设所有的输入都是合法的,将从input元素中获取输入数据
//将百分比格式转换为小数格式,并从年利率转换为月利率
//将年度赔付转换为月度赔付
var principal = parseFloat(amount.value);
var interest = parseFloat(apr.value) / 100 / 12;
var payments = parseFloat(years.value) * 12;
//现在计算月度赔付的数据
var x = Math.pow(1 + interest, payments); // Math.pow()进行幂次运算
var monthly = (principal * x * interest) / (x - 1);
//如果结果没有超过JavaScript能表示的数字范围,且用户的输入也正确
//这里所展示的结果就是合法的
if (isFinite(monthly)) {
//将数据填充至输出字段的位置,四舍五入到小数点后两位数字
payment.innerHTML = monthly.toFixed(2);
total.innerHTML = (monthly * payments).toFixed(2);
totalinterest.innerHTML = (monthly * payments - principal).toFixed(2);
//将用户的输入数据保存下来,这样在下次访问时也能取到数据
save(amount.value, apr.value, years.value, zipcode.value);
//找到并展示本地放贷人,但忽略网络错误
try {
// 捕获这段代码抛出的所有异常
getLenders(amount.value, apr.value, years.value, zipcode.value);
} catch (e) {
/*忽略这些异常 */
console.log(e);
}
//最后,用图表展示贷款余额、利息和资产收益
chart(principal, interest, monthly, payments);
} else {
//计算结果不是数字或者是无穷大,意味着输入数据是非法或不完整的
//清空之前的输出数据
payment.innerHTML = ''; // 清空元素的文本内容
total.innerHTML = '';
totalinterest.innerHTML = '';
chart(); //不传参数的话就是清除图表
}
}
//将用户的输入保存至1ocalstorage对象的属性中
//这些属性在再次访间时还会继续保持在原位置
//如果你在浏览器中按照fle://URL的方式直接打开本地文件,
//则无法在某些浏览器中使用存储功能(比如FireFox)
//而通过HTTP打开文件是可行的
function save(amount, apr, years, zipcode) {
if (window.localstorage) {
// 只有在浏览器支持的时候才运行这里的代码
localStorage.loan_amount = amount;
localStorage.loan_apr = apr;
localStorage.loan_years = years;
localStorage.loan_zipcode = zipcode;
}
}
//在文档首次加载时,将会尝试还原输入字段
window.onload = function () {
//如果浏览器支持本地存储并且上次保存的值是存在的
if (window.localstorage && localstorage.loan_amount) {
document.getElementById('amount').value = localStorage.loan_amount;
document.getElementById('apr').value = localStorage.loan_apr;
document.getElementById('years').value = localStorage.loan_years;
document.getElementById('zipcode').value = localStorage.loan_zipcode;
}
};
//将用户的输入发送至服务器端脚本(理论上)将
//返回一个本地放贷人的链接列表,在这个例子中并没有实现这种查找放贷人的服务
//但如果该服务存在,该函数会使用它
function getLenders(amount, apr, years, zipcode) {
//如果浏览器不支持XMLHttpRequest对象,则退出
if (!window.XMLHttpRequest) return;
//找到要显示放贷人列表的元素
var ad = document.getElementById('lenders');
// 如果返回为空,则退出
if (!ad) return;
//将用户的输入数据进行URL编码,并作为查询参数附加在URL里
var url =
'http://127.0.0.1:8080/getlenders.php' + //处理数据的URL地址
'?amt=' +
encodeURIComponent(amount) + // 使用查询串中的数据
'&apr=' +
encodeURIComponent(apr) +
'&yrs=' +
encodeURIComponent(years) +
'&zip=' +
encodeURIComponent(zipcode);
//通过XMLHttpRequest对象来提取返回数据
var xhttp = new XMLHttpRequest(); //发起一个新的请求
xhttp.open('GET', url); // 通过URL发起一个HTTP GET请求
xhttp.send(null); //不带任何正文发送这个请求
//在返回数据之前,注册了一个事件处理函数,这个处理的数
//将会在服务器的响应返回至客户端的时候调用
//这种异步编程模型在客户端]avascript中是非常常见的
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4 && xhttp.status == 200) {
//如果代码运行到这里,说明我们得到了一个合法且完整的HTTP响应
var response = xhttp.responseText; // HTTP响应是以字符串的形式呈现的
var lenders = JSON.parse(response); //将其解析为]S数组
//将数组中的放贷人对象转换为HTML字符串形式
var list = '';
for (var i = 0; i < lenders.length; i++) {
list +=
"<li><a href='" +
lenders[i].url +
"'>" +
lenders[i].name +
'</a>';
}
//将数据在HTML元素中呈现出来
ad.innerHTML = '<ul>' + list + '</ul>';
}
};
}
//在HTML<canvas>元素中用图表展示月度贷款余额、利息和资产收益
//如果不传入参数的话,则清空之前的图表数据
function chart(principal, interest, monthly, payments) {
var graph = document.getElementById('graph'); //得到<canvas>标签
graph.width = graph.width; //用一种巧妙的手法清除并重置画布
//如果不传入参数,或者浏览器不支持画布,则直接返回
if (arguments.length == 0 || !graph.getContext) return;
// 获得画布元素的"context"对象,这个对象定义了一组绘画API
var g = graph.getContext('2d'); //所有的绘画操作都将基于这个对象
var width = graph.width,
height = graph.height; // 获得画布大小
//这里的函数作用是将付款数字和美元数据转换为像素
function paymentToX(n) {
return (n * width) / payments;
}
function amountToY(a) {
return height - (a * height) / (monthly * payments * 1.05);
}
//付款数据是一条从(0,0)到(payments,monthly*payments)的直线
g.moveTo(paymentToX(0), amountToY(0)); //从左下方开始
g.lineTo(
paymentToX(payments), //绘至右上方
amountToY(monthly * payments)
);
g.lineTo(paymentToX(payments), amountToY(0)); // 再至右下方
g.closePath(); //将结尾连接至开头
g.fillStyle = '#f88'; //亮红色
g.fill(); //填充矩形
g.font = 'bold 12px sans-serif'; //定义一种字体
g.fillText('Total Interest Payments', 20, 20); //将文字绘制到图例中
//很多资产数据并不是线性的,很难将其反映至图表中
var equity = 0;
g.beginPath(); //开始绘制新图形
g.moveTo(paymentToX(0), amountToY(0)); // 从左下方开始
for (var p = 1; p <= payments; p++) {
//计算出每一笔赔付的利息
var thisMonthsInterest = (principal - equity) * interest;
equity += monthly - thisMonthsInterest; //得到资产额
g.lineTo(paymentToX(p), amountToY(equity)); //将数据绘制到画布上
}
g.lineTo(paymentToX(payments), amountToY(0)); //将数据线绘制至x轴
g.closePath(); //将线条结尾连接至线条开头
g.fillstyle = 'green'; //使用绿色绘制图形
g.fill(); //曲线之下的部分均填充
g.fillText('Total Equity', 20, 35); //文本颜色设置为绿色
//再次循环,余额数据显示为黑色粗线条
var bal = principal;
g.beginPath();
g.moveTo(paymentToX(0), amountToY(bal));
for (varp = 1; p <= payments; p++) {
var thisMonthsInterest = bal * interest;
bal -= monthly - thisMonthsInterest; //得到资产额
g.lineTo(paymentToX(p), amountToY(bal)); //将直线连接至某点
}
g.linewidth = 3; //将直线宽度加粗
g.stroke(); //绘制余额的曲线
g.fillstyle = 'black'; // 使用黑色字体
g.fillText('Loan Balance', 20, 50); //图例文字
//将年度数据在X轴做标记
g.textAlign = 'center'; //文字居中对齐
var y = amountToY(0); // Y坐标设为0
for (var year = 1; year * 12 <= payments; year++) {
//谝历每年
var x = paymentToX(year * 12); //计算标记位置
g.fillRect(x - 0.5, y - 3, 1, 3); //开始绘制标记
if (year == 1) g.fillText('Year', x, y - 5); //在坐标轴做标记
if (year % 5 == 0 && year * 12 !== payments)
//每5年的数据
g.fillText(string(year), x, y - 5);
}
//将赔付数额标记在右边界
g.textAlign = 'right'; //文字右对齐
g.textBaseline = 'middle'; //文字垂直居中
var ticks = [monthly * payments, principal]; //我们将要用到的两个点
var rightEdge = paymentToX(payments); // 设置X坐标
for (var i = 0; i < ticks.length; i++) {
//对每两个点做循环
var y = amountToY(ticks[i]); //计算每个标记的Y坐标
g.fillRect(rightEdge - 3, y - 0.5, 3, 1); //绘制标记
g.fillText(
String(ticks[i].toFixed(0)), //绘制文本
rightEdge - 5,
y
);
}
}
</script>
</body>
</html>
1.2.2 后端代码
1.2.2.1 后端控制层
package xm.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author heliming
* @version 1.0
* @date 2024/4/30-19:29
* @description TODO
*/
@RestController
public class HelloController {
//http://getlenders.php/?amt=100&apr=2&yrs=20&zip=23
// lenders[i].url +
// "'>" +
// lenders[i].name +
@GetMapping("getlenders.php")
public List<Map<String, String>> hello(Integer amt, Integer apr, Integer yrs, Integer zip) {
List<Map<String, String>> result = new ArrayList<>();
Map<String, String> obj1 = new HashMap<>();
obj1.put("url", "https://www.baidu.com");
obj1.put("name", "百度");
result.add(obj1);
Map<String, String> obj2 = new HashMap<>();
obj2.put("url", "https://www.taobao.com");
obj2.put("name", "淘宝");
result.add(obj2);
System.out.println(result);
return result;
}
}
1.2.2.1 后端解决跨域
package xm.conf;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*") // 允许的前端域名或地址
.allowedMethods("GET", "POST") // 允许的请求方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 允许携带凭证(如Cookie)
.maxAge(3600); // 缓存预检请求的时间,单位秒
}
}
1.2.3 图片