project from jirengu.com fangyinghang Frontend class
demo实现的功能:
新建src文件夹
- index.html
把meta view-port改为taobao标准版:
搜索m.taobao.com > F12 > 元素 > head > meta name="viewport" > 右键复制 > 复制 outerHTML > 粘贴到index里面
<script src="main.js"></script>
建立服务器: vscode打开终端 >
parcel src/index.html
- main.js
- 创建4个div,后期会改为section:
快速输入
div id=""的方法是#app1+#app2+#app3+#app4,然后按Tab键
快速输入div class=""的方法是.app1+.app2+.app3+.app4,然后按Tab键
<body>
<div class="page">
<section id="app1">
<div class="output">
<span id="number">100</span>
</div>
<div class="actions">
<button id="add1">+1</button>
<button id="minus1">-1</button>
<button id="mul2">*2</button>
<button id="divide2">÷2</button>
</div>
</section>
<section id="app2">
<ol class="tab-bar"> //监听li时作为索引
<li>1</li>
<li>2</li>
</ol>
<ol class="tab-content">
<li>内容1</li>
<li>内容2</li>
</ol>
</section>
<section id="app3">
<div class="square"></div>
</section>
<section id="app4">
<div class="circle"></div>
</section>
</div>
<script src="main.js"></script>
</body>
- 引入css的方法:
在index的head标签里面,写
<link rel="stylesheet" href="app1.css">
在main.js里面,写import './app1.css'
- app1.css里面的内容:
#app1{}
#app1 .output{}
#app1 .action{}
- reset.css的引入在
main.js里面加一行import './reset.css',其里面的内容:
*{margin:0;padding:0}
- 安装
jquery的方法,在终端中输入如下命令:
yarn init
yarn add jquery
-
引入
jquery的方法,在main.js中,增加一行import $ from 'jquery' -
获取到button,需要使用div的id索引到每个button,
const $button1 = $('#add1');
const $button2 = $('#minus1');
const $button3 = $('#mul2');
const $button4 = $('#divide2');
const $number = $('#number');
- 点击事件:事件处理器(event handler)
target.onclick = functionRef;
functionRef是一个函数名称,或一个 函数表达式。该函数接收MouseEvent对象作为其唯一参数。在函数内,this是触发当前事件的元素(同时匹配event.currentTarget)。MouseEvent对象有单击click、双击dblclick、松开Mouseup、按下Mousedown。
- 函数表达式的语法为:
let function_expression = function [name]([param1[, param2[ , ..., paramN]]]) {
statements
};
name函数名称。可被省略,此种情况下的函数是匿名函数(anonymous)。 函数名称只是函数体中的一个本地变量。paramN被传递给函数的一个参数名称。statements构成函数体的语句。
$button1.on('click',() => {
let n = parseInt($number.text());
n += 1;
localStorage.setItem('n',n) //把每次运算的结果,保存到本地,确保用户刷新时,数值不变
$number.text(n);
});
按照上面的思路,把-1,x2,/2都实现,但是埋下一个伏笔,此时代码已经有重复的情况,有优化的空间。
- 计算的过程
const n = localStorage.getItem('n');
$number.text(n || 100);
-
滚动条的宽度14-19px左右;
-
模块化:把一个功能放在一个模块里
import "./reset.css";
import './global.css';
import './app1.css'; //可以挪到app1.css的文件里面
import './app1.js';
import "./app2.css" //可以挪到app2.css的文件里面
import './app2.js'
- 实现app2的功能:
import $ from "jquery"; //不会多次加载jquery
const $tabBar = $("#app2 .tab-bar"); //定义 $tabBar 是app2里面的tab-bar
const $tabContent = $('#app2 .tab-content')
//监听两个li的父元素<ol class="tab-bar"> 点击事件,此为事件委托
$tabBar.on("click", "li", e =>{
const $li = $(e.currentTarget);
const index = $li.index(); //看一下点击的li排行老几
$tabContent.children().eq(index).css({display:'block'})
});
12.1 如何知道一个元素在他的兄弟中排行老几,就是遍历他的兄弟,然后看第几个兄弟跟他是一样的,jqurey内置了上述的这个方法($li.index()),首先拿到用户点击的这个元素,e.target是用户点击的元素,而e.currentTarget才是开发者想监听的元素,也就是此例中的li
12.2 获取到了第几个以后,就可以把ol class="tab-content"下面的(children)两个li,等于第index个(.eq(index))对应display:block(.css({display:'block'})),同时通过链式操作找到他的兄弟(.siblings().css({display:'none'})),完整的代码如下:
$tabContent.children().eq(index).css({display:'block'}).siblings().css({display:'none'})
//找到tabContent的儿子们,等于第index个的css变成display:block,同时他的兄弟的css变成display:none
12.3 但是上面的.css()或.show()和.hide()这三个API,不能使用,需要替换为.addClass('active')和removeClass('active')这样就避免JS跨界去管样式的情况,只由CSS去自己解决样式问题,各干各的事。
$tabContent.children().eq(index).addClass('active').siblings().removeClass('active')
#app2{
border:1px solid blue;
}
#app2 .tab-bar{
display:flex;
}
#app2 .tab-bar > li {
border: 3px solid black;
width: 50%;
}
#app2 .tab-content{
}
#app2 .tab-content > li{
display:none;
}
#app2 .tab-content > li.active{ //如果li拥有active类,
display:block;
}
12.4 以上3步(12.1-12.3)的思想是样式与行为分离,JS只管功能,CSS只管样式;
12.5 实现背景色切换功能:
$li.addClass('selected').siblings().removeClass('selected')
#app2 .tab-bar > li.selected{
background: yellow;
color: white;
}
12.6 刚进入页面时,既不显示1,也不显示2,那就预先初始化一个触发click的tab:
$tabBar.children().eq(0).trigger('click')
12.7 添加数据保存功能:
const localKey = 'app2.index'
const index = localStorage.getItem('localKey') || 0 //保底值为0
const index = $li.index();
localStorage.setItem(localKey, index) //设置localKey 为index
$tabBar.children().eq(index).trigger('click')
- 实现app3的功能:
import $ from 'jquery'
import './app3.css'
const $square = $('#app3 .square')
const localKey = 'app3.active'
// 有三种情况yes,no,undefined(默认)
//const active = localStorage.getItem(localKey) === 'yes' ?true :false
const active = localStorage.getItem(localKey) === 'yes'
if(active){
$square.addClass('active')
}else{
$square.removeClass('active')
}
//以上三行代码也等价于 `$square.toggleClass('active',active)`
$square.on('click',()=>{
if($square.hasClass('active')){
$square.removeClass('active')
localStorage.setItem(localKey,'no')
}else{
$square.addClass('active')
localStorage.setItem(localKey,'yes')
}
})
#app3{
};
#app3 .square{
border: 1px solid grey;
margin-top:10vw;
margin-left:10vw;
width:10vw;
height: 10vw;
};
#app3 .square.active{
transform:translateX(15vw); //往右平移
}
- 实现app4的功能:
import $ from 'jquery'
import './app4.css'
const $circle = $('app4 .circle')
$circle.on('mouseenter',()=>{
$circle.addClass('active')
}).on('mouseleave',()={
$circle.removeClass('active')
})
#app4{
}
@keyframes change{
0%{background: red}
100%{background: blue}
}
#app4 .circle{
width: 30vw;
height: 30vw;
border-radius: 50%;
}
#app4 .circle.active{
animation: change 1s infinite alternate linear;
}