一、MVC是什么?
- 设计是个框,什么都能往里装
- MVC是设计模式的一种,但它太著名了,就不用称之为设计模式
1.设计模式的定义
- 代码写得特别好,别人肯定也用得到
- 给这种写法取个名字,比如适配器模式
(如果是IE就做什么,如果是Chrome就做什么) - 设计模式就是对通用代码取个名字而已
2.为什么有设计模式
- DRY原则:Don’t Repeat Yourself
不要重复自己
3.什么是重复
- 代码级别的重复:相同的三行代码写了两遍
解决:那就应该重构它,给取一个名字,放入函数中,调用这个函数 - 页面级别重复:类似的页面做了10遍
解决:想出一个万金油写法,任何情况下都可以用 - MVC就是一个万金油设计模式
所有页面都可以使用MVC来优化代码结构
MVC就是用来解决页面代码过于重复的问题
4.MVC是什么
- 每个模块都可以写成三个对象,分别是 M、V、C
- M - Model(数据模型),负责操作所有数据
- V - View(视图),负责所有 UI 界面
- C - Controller(控制器),负责其他操作
二、验证MVC–四个模块
1.四个需求
- MVC包含:模块、类
- 验证:每个模块就好像一个小工具给用户使用,用户使用的时候模块是独立的
1.运算器
2.Tab切换
3.动画
4.渐变 - 如何使用MVC使得代码很严谨
2.引入文件
- 四个模块就写四个section(不写div以表示区别)
- 想要四个模块分别占据页面的四分之一,则使用flex布局
1.使用div.page包裹四个div模块
2.新建一个global.css,使用main.js引用
body > .page
:只管body里面的page,如果是body里面的里面的page,就不管了
body{
/*这个办法暂时使用*/
overflow: hidden;
}
body > .page{
display:flex;
flex-wrap:wrap;
}
body >.page > section{
width: 50vw;
height: 50vh;
}
- 注意:要考虑页面滚动条的宽度(17px)
1.所有浏览器窗口滚动条大概就是 14px~19px
2.滚动条的宽度会影响页面布局,如使用flex布局
3.当两个模块宽都是50vw的时候,是没办法占据左右屏幕的,50vw*2 - 17px = 屏幕宽度
4.解决:让滚动条隐藏,overflow:hidden
(这个办法是暂时的,因为如果模块过多一页面装不下就需要滚动,那时候就需要滚轮滚动,然后滚动条就只隐藏起来就好,不用这个办法,皮卡丘中有)
2.1 一个全新的CSS文件引入方法
- 以前是在head中添加link
- 现在使用JS来引入,在main.js文件中写入
import './xxx.css'
- CSS 代码就不都装在一个文件里了,分成几个不同的子文件(然后都在JS中引入)
2.2 一个全新的方法引入jQuery
- 以前是用script直接引入
- 现在使用npm
- 新建终端 – 初始化:
yarn init -y
– 安装:yarn add jquery
或npm i jquery
- 安装好后多了很多文件
1.node_modules文件中就有jquery,jquery里面就是源代码
2.package.json文件:里面写了初始化信息,还写了版本号,因为不然下次这个项目安装jQuery版本就不一样了,所以需要记下版本号
3.yarn.lock文件:写明了这个jQuery是从哪里下载的,这样以后再安装的时候就知道从哪里下的 - 使用JS文件引入jQuery
import $ from 'jquery'
这个$
就是jQuery变量,可以改其他名字,但一般默认用这个
注意名字是小写
2.3 关于API的使用法则
- 关于API(如import)的使用,不要站在使用者的立场去思考
- 要站在设计代码的人的立场去思考,我该怎么设计用户才能使用得更方便
- 这就是封装
3.代码
3.1 模块化
- 为什么要模块化?
答:因为4个模块的代码互不相干,包括CSS代码、JS代码都是互不干扰的,放在一起非常不好看 - 如何模块化?
答:创建不同的文件分割开。
如CSS代码:reset.css、global.css、app1.css、app2.css、app3.css、app4.css等等
如JS代码:app1.js、app2.js、app3.js、app4.js - 引入模块
答:在main.js文件中使用import引入四个相应app.js文件,然后再对应的app.js文件中引入自己的app.css文件
整体的css文件还是引入main.js中
注意:尽量不要用css的import,因为性能比较低。
3.2 运算器
- 给按钮加id,拿到四个按钮
- 给四个按钮绑定事件
- 加法器、减法器、乘法器、除法器代码都差不多,稍微做修改
- 刷新又回到当前数字:每次改变都存到
localStorage
里面
$button1.on('click',()=>{
let n = parseInt($number.text())//获取id为number的标签文字内容
n += 1
localStorage.setItem("n",n)//取名为n,从n获取内容,保存当前的n
$number.text(n)
})
- 初始化n
const n = localStorage.getItem("n")//从localStorage中获取n
$number.text(n || 100)//n存在就给number,不存在就给100
3.3 tab切换
- 添加CSS文件,用JS引入
- 使用ol和li创建一个表格,加上相应的类
<div id="app2">
<ol class="tab-bar">
<li></li>
<li></li>
</ol>
<ol class="tab-content">
<li></li>
<li></li>
</ol>
</div>
- app2.css文件中所有都加上
.app2
的前缀,就不怕和其他的冲突了 - 当使用jQuery查找元素时,如果两个标签中有同一个类名的标签,那么就加上前缀
const $tabBar = $('#app2 .tab-bar')
:意思是查找ID为app2标签中的tab-bar - 事件委托
(也就是监听父元素tabBar,但其实可以监听父元素中任意子元素li的点击事件)
1.这样有多少子元素就可以省多少个监听
2.但是需要拿到用户点击的是第几个li元素:
e.currentTarget
就是用户点击的li
元素
注意:e.target
是用户点击的元素,li里面还有元素,那么就是里面的
实在不知道两个怎么区分,就一个一个试
3.不要用DOM元素,非常难用,使用jQuery封装的DOM元素(含有 $ 的元素) - 获取到用户点击的是第几个li后,展示第几个li的内容content
1.获取到tabContent
2.然后根据index找到相应的content,修改其css的display(前面是none,修改为block) - 注意:永远不要在JS中用直接操作CSS的API!!!
(如:.css
、.show
、.hide
)
应该用:.addClass('active')
和.removeClass('active')
这样JS就不用管css怎么写,css自己去管 - add之后就会在点击后相应的li标签中添加class类名,名为:active
remove则删除相应类名 - 背景色切换同理,给相应li添加类selected
const $tabBar = $("#app2 .tab-Bar")
const $tabContent = $("#app2 .tab-Content")
$tabBar.on('click','li',(e)=>{
const $li = $(e.currentTarget))//jQuery封装的DOM元素
const index = $li.index()//获取是第几个li
// 链式操作
$li//背景色切换
.addClass('selected')
.siblings.removeClass('selected')
$tabContent.children()//内容切换,找到content的孩子
.eq(index).addClass('active')//eq是等于的意思,找到第index个孩子
.siblings().removeClass('active')//删除其他兄弟的class,主要是在第二次点击li时
})
- 由CSS来操作显示和隐藏、背景色切换
如果这个li拥有active类,则:display: block
#app2 .tab-content >li.selected{
background: rgb(253,221,155);
color:white;
}
#app2 .tab-content >li.active{
display: block;
}
- 想要一进入页面就默认在1,给与相应的颜色和内容
则:在JS中添加默认点击事件
$tabBar.children().eq(0).trigger('click')
- 想让页面记住所在的位置,刷新还是一样
const localKey = 'app2.index'
const index = localStorage.getItem(localKey) || 0 //保底值
$tabBar.on("click", "li", (e) => {
略
const index = $li.index();
localStorage.setItem(localKey,index)//保存位置
});
$tabBar.children().eq(index).trigger("click");
- 这是基于:样式与行为分离
1.JS只管功能,不管长什么样
2.CSS只管样式,不管功能
3.4 动画
- 想要点击之后移动
- 创建app3.js和app3.css,在main.js中引入JS文件,在app3.js中引入CSS文件
- 添加一个div.square
- 获取元素然后监听点击事件,点击后加个类(active)
永远不要用jQuery操作样式!!! - 在css文件中,给默认样式方形square样式
如果square有类active,给样式
注意:不想闪现记得在square中添加过渡:transition: transform 1s;
app3 .square.active{
transform:translateX(15vw);/*x方向移动*/
}
- 想要点击以下移过去,再点击一下移回来
不需要添加两个点击事件,只需要在点击里面看有没有class,如果有就删掉,没有就加上
jQuery内置该操作:$square.toggleClass('active')
- toggleClass有个bug,就是想要保存当前位置然后刷新页面时不会告诉状态,因此还是使用if…else…来判断,可以记录位置
3.5 动画2
- 点击之后渐变
- 添加一个 div.circle,其他和上一个动画差不多
- 想要鼠标浮上去变色,则添加一个监听
鼠标移进去添加类,鼠标移出去删掉类
$circle.on('mouseenter',()={
$circle.addClass('active')
}).on('mouseleave',()=>{
$circle.removeClass('active')
})
- 给circle添加样式
如果square有类active,给一个渐变动画(先声明一个动画)
@keyframes change{
0%{
background: red;
}
100%{
background: blue;
}
}
app4 .square{
略;
}
app4 .square.active{
animation: change 1s infinite alternate linear;
/*动画,1s,无限,来回,线性*/
}