Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f494a3e
Merge pull request #36 from dashrun/master
soyaine Oct 29, 2017
c2d79bd
Merge pull request #37 from dashrun/master
soyaine Nov 1, 2017
fd50d02
Merge pull request #39 from dashrun/master
soyaine Nov 12, 2017
76949a9
Change my name online
soyaine Dec 29, 2017
a5d97a5
替换第19~28项的Demo跳转链接
experdot Jan 5, 2018
3ec39d4
Merge pull request #43 from experdot/master
soyaine Jan 8, 2018
b8fce47
Update index-SOYAINE.html
fyzhu Mar 6, 2018
4a74e8e
Merge pull request #44 from fyzhu/patch-1
soyaine Mar 6, 2018
a9b940d
更新了readme文件中的示意图链接
dashnowords Jul 17, 2018
3c3b8e0
Merge branch 'master' into master
dashnowords Jul 17, 2018
da49c1d
fix typo `tranform-origin`
soyaine Jul 23, 2018
e0e6705
Create .gitattributes
dashnowords Sep 19, 2018
84f6d0b
Merge pull request #49 from dashnowords/master
soyaine Oct 30, 2018
f55e0ab
fix issue #57 #54 #53 #51 #41 #32
soyaine Dec 5, 2018
f91b4a2
fix issue #56 #55
soyaine Dec 6, 2018
d311720
fix #58 and lint code
soyaine Jun 25, 2019
202e91f
style: lint code
soyaine Jun 27, 2019
8e6eeda
remove videos link note #60
soyaine Jul 14, 2021
0a6c3e4
update nickname
soyaine Jul 14, 2021
f4232a6
fix #65 修复一些问题
soyaine Jul 11, 2022
59f2b7c
fix #58 variable name
soyaine Jun 25, 2019
f889ba1
style: lint comment code
soyaine Jun 25, 2019
bef7bbf
typo: change 'asset' to 'assert'
longlin10086 Oct 14, 2024
fc41f58
Merge pull request #67 from longlin10086/master
soyaine Oct 18, 2024
c3d9264
fix #68
soyaine Nov 10, 2025
a934c4a
fix #68
soyaine Nov 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.html linguist-language=javascript
4 changes: 2 additions & 2 deletions 01 - JavaScript Drum Kit/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 01 JavaScript Drum Kit 中文指南

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[未枝丫](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 1 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

## 实现效果
Expand Down Expand Up @@ -92,7 +92,7 @@ audio.play();

### 如何使页面按钮恢复原状?

利用一个叫 [`transitionened`](https://developer.mozilla.org/zh-CN/docs/Web/Events/transitionend) 的事件,它在 CSS transition 结束后会被触发。我们就可以利用这个事件,在每次打鼓的效果(尺寸变大、颜色变化)完成之后,去除相应样式。
利用一个叫 [`transitionend`](https://developer.mozilla.org/zh-CN/docs/Web/Events/transitionend) 的事件,它在 CSS transition 结束后会被触发。我们就可以利用这个事件,在每次打鼓的效果(尺寸变大、颜色变化)完成之后,去除相应样式。

在这个页面中,发生 `transition` 的样式属性不止一个(`box-shadow`, `transform`, `border-color`),所以需要添加一个判断语句,使每发生一次按键事件时,只去除一次样式。

Expand Down
8 changes: 4 additions & 4 deletions 02 - JS + CSS Clock/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 02 纯 JS、CSS 时钟 中文指南

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[未枝丫](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 2 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

> 创建时间:2016-12-21
Expand All @@ -21,7 +21,7 @@
3. 每一秒改变一次指针状态

**涉及到的特性:**
- `transform-oragin`
- `transform-origin`
- `transform: rotate()`
- `transition`
- `transition-timing-function: cubic-bezier(x, x, x, x)`
Expand All @@ -33,10 +33,10 @@
### CSS 部分

1. 调整指针的初始位置以及旋转的轴点
[transform-oragin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)
[transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)

```css
transform-oragin: 100%; // 或者可以用 right
transform-origin: 100%; // 或者可以用 right
```

2. 调整时钟指针跳动时的过渡效果
Expand Down
13 changes: 6 additions & 7 deletions 02 - JS + CSS Clock/index-SOYAINE.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
position: relative;
width: 100%;
height: 100%;
transform: translateY(-3px); /* account for the height of the clock hands */
/* transform: translateY(-3px); /* account for the height of the clock hands */
/* canceled according to https://github.com/soyaine/JavaScript30/issues/55 */
}

.hand {
Expand Down Expand Up @@ -87,8 +88,6 @@
0 0 0 2px rgba(0,0,0,0.1),
0 0 10px rgba(0,0,0,0.2);
transform: translate(-50%, -50%);
/*transition: all .05s;*/

}

.hour-hand {
Expand All @@ -104,15 +103,15 @@
width: 45%;
height:5px;
margin-top: -2.5px;
transition: all .1s;
transition: all .1s cubic-bezier(0.9, 0.54, 0.26, 1.68);
}

.second-hand {
height: 2px;
margin-top: -1px;
border-bottom-left-radius: 100%;
border-top-left-radius: 100%;
transition: all .05s;
transition: all .05s cubic-bezier(0.9, 0.54, 0.26, 1.68);
background-color: red;
}

Expand Down Expand Up @@ -141,10 +140,10 @@
// 解决指针跳顿问题【第一种方法】
// 在发生跳顿的角度值处,将 CSS 的 `transition` 属性去掉
if (secondDeg === 90) secHand.style.transition = 'all 0s';
else secHand.style.transition = 'all 0.05s';
else secHand.style.transition = 'all 0.05s cubic-bezier(0.9, 0.54, 0.26, 1.68)';

if (minDeg === 90) minHand.style.transition = 'all 0s';
else minHand.style.transition = 'all 0.1s';
else minHand.style.transition = 'all 0.1s cubic-bezier(0.9, 0.54, 0.26, 1.68)';

// 时针间距过大不做处理
// if (hourDeg === 116.5) hourHand.style.transition = 'all 0s';
Expand Down
2 changes: 1 addition & 1 deletion 03 - CSS Variables/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 03 CSS Variable

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[未枝丫](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 3 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

## 实现效果
Expand Down
6 changes: 3 additions & 3 deletions 04 - Array Cardio Day 1/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 04 Array Cardio 💪 指南一

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[Soyaine](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 4 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

## 实现效果
Expand All @@ -23,11 +23,11 @@ console.table(thing)

1. 筛选 16 世纪出生的发明家
2. 展示他们的姓和名
3. 把他们按照年龄从大到小进行排序
3. 把他们按照出生日期从大到小进行排序
4. 计算所有的发明家加起来一共活了多少岁
5. 按照他们活了多久来进行排序
6. 筛选出一个网页里含有某个词语的标题
7. 按照姓氏来对发明家进行排序
7. 按照姓氏来进行排序
8. 统计给出数组中各个物品的数量

## 相关知识
Expand Down
2 changes: 1 addition & 1 deletion 04 - Array Cardio Day 1/index-FINISHED.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{ first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
];

const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William'];
const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black, Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William'];

// Array.prototype.filter()
// 1. Filter the list of inventors for those who were born in the 1500's
Expand Down
189 changes: 104 additions & 85 deletions 04 - Array Cardio Day 1/index-SOYAINE.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
</head>
<body>
<p><em>请按 F12 查看 Console 面板</em> 💁</p>
<p>若无结果请刷新试试</p>
<p>若无结果请刷新试试</p>
<script>

// ## Array 基础 Day 1

// Some data we can work with

const inventors = [
Expand All @@ -28,119 +26,140 @@
{ first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
];

const flavours = ['Chocolate Chip', 'Kulfi', 'Caramel Praline', 'Chocolate', 'Burnt Caramel', 'Pistachio', 'Rose', 'Sweet Coconut', 'Lemon Cookie', 'Toffeeness', 'Toasted Almond', 'Black Raspberry Crunch', 'Chocolate Brownies', 'Pistachio Almond', 'Strawberry', 'Lavender Honey', 'Lychee', 'Peach', 'Black Walnut', 'Birthday Cake', 'Mexican Chocolate', 'Mocha Almond Fudge', 'Raspberry'];
const flavours = ['Chocolate Chip', 'Kulfi', 'Caramel Praline', 'Chocolate', 'Burnt Caramel', 'Pistachio',
'Rose', 'Sweet Coconut', 'Lemon Cookie', 'Toffeeness', 'Toasted Almond', 'Black Raspberry Crunch',
'Chocolate Brownies', 'Pistachio Almond', 'Strawberry', 'Lavender Honey', 'Lychee', 'Peach',
'Black Walnut', 'Birthday Cake', 'Mexican Chocolate', 'Mocha Almond Fudge', 'Raspberry'
];

const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry', 'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert', 'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester', 'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano', 'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle', 'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose', 'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black Elk', 'Blair, Robert', 'Blair, Tony', 'Blake, William'];
const people = ['Beck, Glenn', 'Becker, Carl', 'Beckett, Samuel', 'Beddoes, Mick', 'Beecher, Henry',
'Beethoven, Ludwig', 'Begin, Menachem', 'Belloc, Hilaire', 'Bellow, Saul', 'Benchley, Robert',
'Benenson, Peter', 'Ben-Gurion, David', 'Benjamin, Walter', 'Benn, Tony', 'Bennington, Chester',
'Benson, Leana', 'Bent, Silas', 'Bentsen, Lloyd', 'Berger, Ric', 'Bergman, Ingmar', 'Berio, Luciano',
'Berle, Milton', 'Berlin, Irving', 'Berne, Eric', 'Bernhard, Sandra', 'Berra, Yogi', 'Berry, Halle',
'Berry, Wendell', 'Bethea, Erin', 'Bevan, Aneurin', 'Bevel, Ken', 'Biden, Joseph', 'Bierce, Ambrose',
'Biko, Steve', 'Billings, Josh', 'Biondo, Frank', 'Birrell, Augustine', 'Black, Elk', 'Blair, Robert',
'Blair, Tony', 'Blake, William'
];

// Array.prototype.filter()
// 1. Filter the list of inventors for those who were born in the 1500's
// 筛选 16 世纪出生的人
const fifteen = inventors.filter(function(inventor) {
if (inventor.year >= 1500 && inventor.year < 1600 ) {
return true;
}
});
console.table(fifteen);

const __fifteen = inventors.filter(inventor =>(inventor.year >= 1500 && inventor.year < 1600));
console.table(__fifteen);
// 1. 筛选 16 世纪出生的人
const fifteen = inventors.filter(function (inventor) {
if (inventor.year >= 1500 && inventor.year < 1600) {
return true;
}
});
console.log('1. 筛选 16 世纪出生的人');
console.table(fifteen);

const __fifteen = inventors.filter(inventor => (inventor.year >= 1500 && inventor.year < 1600));
console.table(__fifteen);


// Array.prototype.map()
// 2. Give us an array of the inventors' first and last names
// 展示上面发明家的姓名
const fullNames = inventors.map(inventor => inventor.first + ' ' + inventor.last);
// const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`);
console.log(fullNames);

// 展示上面发明家的姓名
console.log('2. 展示上面发明家的姓名');
const fullNames = inventors.map(inventor => inventor.first + ' ' + inventor.last);
// const fullNames = inventors.map(inventor => `${inventor.first} ${inventor.last}`);
console.log(fullNames);


// Array.prototype.sort()
// 3. Sort the inventors by birthdate, oldest to youngest
// 把这些人从大到小进行排序
// const ordered = inventors.sort(function(firstName, secondName) {
// if(firstName.year > secondName.year) {
// return 1; // 对 sort 函数,返回值为 -1 排在前面,1 排在后面
// } else {
// return -1;
// }
// });
// console.table(ordered);

const __ordered = inventors.sort((a, b) => (a > b) ? 1 : -1);
console.table(__ordered);
// 把这些人从大到小进行排序
console.log('3. 把发明家从大到小进行排序');
// const ordered = inventors.sort(function(firstName, secondName) {
// if(firstName.year > secondName.year) {
// return 1; // 对 sort 函数,返回值为 -1 排在前面,1 排在后面
// } else {
// return -1;
// }
// });
// console.table(ordered);

const __ordered = inventors.sort((a, b) => (a.year > b.year) ? 1 : -1);
console.table(__ordered);


// Array.prototype.reduce()
// 4. How many years did all the inventors live
// 他们所有人一共活了多少岁
// 下面三种写法是一样的效果
// var total = 0;
// for(var i = 0; i < inventors.length; i++) {
// total += inventors[i].passed - inventors[i].year;
// }
// console.log(total);
//
// var totalYears = inventors.reduce(function(total, inventor) {
// return total + inventor.passed - inventor.year;
// }, 0);
// console.log(totalYears);

const totalYear = inventors.reduce( (total, inventor) => {
return total + inventor.passed - inventor.year;
}, 0);
console.log(totalYear);
// 他们所有人一共活了多少岁
console.log('4. 所有发明家一共活了多少岁');

// 下面三种写法是一样的效果
// var total = 0;
// for(var i = 0; i < inventors.length; i++) {
// total += inventors[i].passed - inventors[i].year;
// }
// console.log(total);
//
// var totalYears = inventors.reduce(function(total, inventor) {
// return total + inventor.passed - inventor.year;
// }, 0);
// console.log(totalYears);

const totalYear = inventors.reduce((total, inventor) => {
return total + inventor.passed - inventor.year;
}, 0);
console.log(totalYear);

// 5. Sort the inventors by years lived、
// 按照他们在世的岁数进行排序
const oldest = inventors.sort( (a, b) => {
const last = a.passed - a.year;
const next = b.passed - b.year;
return (next < last) ? -1 : 1;
});
console.table(oldest);
// 按照他们在世的岁数进行排序
console.log('5. 按照发明家在世的岁数进行排序');
const oldest = inventors.sort((a, b) => {
const last = a.passed - a.year;
const next = b.passed - b.year;
return (next < last) ? -1 : 1;
});
console.table(oldest);

// 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name
// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

// 这个是超级酷的一个玩法,打开上面的网页。然后输入下面的语句,就可以筛选出页面中含有 'de' 这个词的所有街道的名称

// const category = document.querySelector('.mw-category');
// const links = Array.from(category.querySelectorAll('a'));
// const de = links
// .map(link => link.textContent)
// .filter(streetName => streetName.includes('de'));

// 下面是我在豆瓣里筛选书名里含有 CSS 的书的代码
// https://book.douban.com/tag/web
// const links = document.querySelectorAll('.subject-list h2 a');
// const book = links
// .map(link => link.title)
// .filter(title => title.includes('CSS'));

// 下面是我在豆瓣里筛选书名里含有 CSS 的书的代码
// https://book.douban.com/tag/web
// const links = Array.from(document.querySelectorAll('.subject-list h2 a'));
// const book = links
// .map(link => link.title)
// .filter(title => title.includes('CSS'));


// 7. sort Exercise
// Sort the people alphabetically by last name
// 按照姓氏的字母进行排序
const sortName = inventors.sort( (a, b) => {
return (a.last > b.last) ? 1 : -1;
})
console.table(sortName);


// 按照姓氏(逗号后面的单词)的字母进行排序
console.log('7. 按照people姓氏(逗号后面的单词)的字母进行排序');
const sortName = people.sort((a, b) => {
return (a.split(', ')[1] > b.split(', ')[1]) ? 1 : -1;
})
console.table(sortName);


// 8. Reduce Exercise
// Sum up the instances of each of these
// 统计各个物品的数量
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];
const reduce = data.reduce( (obj, item) => {
if( !obj[item] ) {
obj[item] = 0;
}
obj[item]++;
return obj;
}, {});
console.log(reduce);

// 统计各个物品的数量
console.log('8. 统计各个物品的数量');
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car',
'truck'
];
const reduce = data.reduce((obj, item) => {
if (!obj[item]) {
obj[item] = 0;
}
obj[item]++;
return obj;
}, {});
console.log(reduce);
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion 05 - Flex Panel Gallery/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 05 Flex 实现可伸缩的图片墙 中文指南

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[未枝丫](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 5 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

## 实现效果
Expand Down
2 changes: 1 addition & 1 deletion 06 - Type Ahead/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 06 Fetch 结合 filter 实现快速匹配古诗

> 作者:©[缉熙Soyaine](https://github.com/soyaine)
> 作者:©[未枝丫](https://github.com/soyaine)
> 简介:[JavaScript30](https://javascript30.com) 是 [Wes Bos](https://github.com/wesbos) 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 6 篇。完整指南在 [GitHub](https://github.com/soyaine/JavaScript30),喜欢请 Star 哦♪(^∇^*)

## 实现效果
Expand Down
Loading