blog's People
blog's Issues
vue与MVVM
Vue与MVVM
MVVM
-
MVVM 由 Model,View,ViewModel 三部分构成,Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。
-
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
-
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
Vue与MVVM联系
Vue.js 可以说是MVVM 架构的最佳实践,专注于 MVVM 中的 ViewModel,不仅做到了数据双向绑定,而且也是一款相对比较轻量级的JS 库,API 简洁,很容易上手。Vue的基础知识网上有现成的教程,此处不再赘述, 下面简单了解一下 Vue.js 关于双向绑定的一些实现细节:
Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
-
Observer数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现。
-
Compile 指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。
-
Watcher 订阅者, 作为连接 Observer 和 Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。
-
Dep 消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update方法。
我是这样理解vue框架对应MVVM模型关系的:
-
Observer相当于Model层观察vue实例中的data数据,当数据发生变化时,通知Watcher订阅者。
-
Compile指令解析器位于View层,初始化View的视图,将数据变化与更新函数绑定,传给Watcher订阅者。
-
Watcher是整个模型的核心,对应ViewModel层,连接Observer和Compile。所有的Watchers存于Dep订阅器中,Watcher将Observer监听到的数据变化对应相应的回调函数,处理数据,反馈给View层更新界面视图。
JS原型链
原型链、继承
new 的过程发生了什么?
function A(name){
this.name = name
}
let a = new A('hehe')
-----------------
let obj = new Object()
obj.__proto__ = A.prototype
A.call(obj, 'hehe')
return obj
- 用new Object() 的方式新建了一个对象 obj
- 将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
- 使用 call,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
- 返回 obj
原型链和prototype属性
上面的 proto 是什么?
就是原型链,原型链是内部 [ [Prototype ]],指向它“父类”的prototype。
打开浏览器控制台,可以看到函数变量都有一个prototype属性(箭头函数没有)。
通过这一句a.proto = A.prototype; 说明a的原型链就是指向函数A的prototype属性。
这里就有一个重要的认识了,虽然名字很像,但是原型链并不是prototype属性,同时原型链指向“父类”的prototype。几乎所有对象都有原型链(除了null和undefined),通过__proto__ 可以看到原型链指向什么(当然最好使用 Object.getPrototypeOf 取原型链)
通过实验可以发现,js中对象的链可以非常复杂。
一图胜千言。这里借两张图。
简而言之
-
函数对象,Function,Object,Array等等的原型链都指向Function.prototype
-
通过new操作符创建的对象原型链指向原来的函数的prototype属性
-
Object.prototype属性的原型链指向null(到null就停止了)
-
而Function.prototype(Array,Date,String等等),以及函数对象的prototype,原型链都指向Object.prototype
所以,原型链一共就分为两类:
- 原型指向Function.prototype的函数们
- 原型指向Object.prototype的对象们
constructor
- 所有函数的prototype.constructor都指向自己
- 因此所有new出来的对象也都有一个reference找到自己的构造函数
小结
-
每个对象都有__proto__属性,但只有函数对象才有prototype属性
-
创建函数时,js会为函数自动添加prototype属性,它的值是空对象,而把函数当作构造函数调用时就会启动new的过程
-
每个js对象一定对应一个原型对象,并从原型对象上继承属性和方法(此处涉及设计模式中原型模式的内容)
-
对象的__proto__属性的值就是他所对应的原型对象
-
所以__proto__才是原型链
继承
JQuery架构
JQuery架构
Jquery内部结构图
(function(window) {
// jQuery 变量,用闭包避免环境污染
var jQuery = (function() {
var jQuery = function(selector, context) {
return new jQuery.fn.init(selector, context, rootjQuery);
};
// 一些变量声明
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function(selector, context, rootjQuery) {
}
// 原型方法
};
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function() {};//jQuery的扩展方法
jQuery.extend({
// 一堆静态属性和方法
// 用 extend 绑定,而不是直接在 jQuery 上写
});
return jQuery;
})();
// 工具方法 Utilities
// 回调函数列表 Callbacks Object
// 异步队列 Defferred Object
// 浏览器功能测试 Support
// 数据缓存 Data
// 队列 Queue
// 属性操作 Attributes
// 事件系统 Events
// 选择器 Sizzle
// DOM遍历 Traversing
// 样式操作 CSS(计算样式、内联样式)
// 异步请求 Ajax
// 动画 Effects
// 坐标 Offset、尺寸 Dimensions
window.jQuery = window.$ = jQuery;
})(window);
CSS双栏式布局
双栏式布局
页面布局中经常用会遇到左侧宽度自适应,右侧固定宽度,或者左侧宽度固定,右侧自适应。总之就是一边固定宽度,一边自适应宽度。
一般固定宽度是导航栏,自适应宽度的是主体内容显示区。
所以要实现这种布局,就先给出如下html结构:
<div class="container">
<div class="sidebar">导航区域</div>
<div class="main">主体内容显示区域</div>
</div>
<div class="footer">footer保证前面的不会影响此元素的显示</div>
container用于包裹sidebar与main,footer用来测试前面的布局不会影响footer的正常显示,如果footer样式不对,说明我们的布局是有问题的。
接下来看常见的几种布局方法:
固定区域浮动,自适应区域不设置宽度但设置margin
.container {
overflow: hidden;
*zoom: 1;
}
.sidebar {
float: right;
width: 300px;
background: #333;
}
.main {
margin-right: 320px;
background: #666;
}
.footer {
margin-top: 20px;
background: #ccc;
}
其中,sidebar让它浮动,并设置了一个宽度;而main没有设置宽度。
大家要注意html中必须使用div标签,不要妄图使用什么p标签来达到目的。因为div有个默认属性,即如果不设置宽度,那它会自动填满它的父标签的宽度。这里的main就是例子。
当然我们不能让它填满了,填满了它就不能和sidebar保持同一行了。我们给它设置一个margin。由于sidebar在右边,所以我们设置main的margin-right值,值比sidebar的宽度大一点点——以便区分它们的范围,例子中是320。
假设main的默认宽度是100%,那么它设置了margin后,它的宽度就变成了100%-320,此时main发现自己的宽度可以与sidebar挤在同一行了,于是它就上来了。
而宽度100%是相对于它的父标签来的,如果我们改变了它父标签的宽度,那main的宽度也就会变——比如我们把浏览器窗口缩小,那container的宽度就会变小,而main的宽度也就变小,但它的实际宽度100%-320始终是不会变的。
这个方法看起来很完美,只要我们记得清除浮动(这里我用了最简单的方法),那footer也不会错位。而且无论main和sidebar谁更长,都不会对布局造成影响。
但实际上这个方法有个很老火的限制——html中sidebar必须在main之前!
但我需要sidebar在main之后!因为我的main里面才是网页的主要内容,我不想主要内容反而排在次要内容后面。
但如果sidebar在main之后,那上面的一切都会化为泡影。
可能有的人不理解,说你干嘛非要sidebar在后面呢?这个问题说来话长,反正问题就是——main必须在sidebar之前,但main宽度要自适应,怎么办?
下面有两个办法,不过我们先把html结构改成我们想要的样子:
<div class="container">
<div class="main">主体内容显示区域</div>
<div class="sidebar">导航区域</div>
</div>
固定区域使用定位,自适应区域不设置宽度但设置margin
我们把sidebar扔掉,只对main设置margin,那么我们会发现main的宽度就已经变成自适应了——于是main对sidebar说,我的宽度,与你无关。
main很容易就搞定了,此时来看看sidebar,它迫不得已抛弃了float。我们来看看sidebar的特点:在右边,宽度300,它的定位对main不影响——很明显,一个绝对主义分子诞生了。
于是我们的css如下:
.container {
position: relative;
}
.sidebar {
position: absolute;
top: 0;
right: 0;
width: 300px;
background: #333;
}
.main {
margin-right: 320px;
background: #666;
}
这段css中要注意给container加上了相对定位,以免sidebar太绝对了跑到整个网页的右上角而不是cintainer的右上角。
好像完成了?在没有看footer的表现时,我很欣慰。我们来把sidebar加长100px。
咦,好像不对,footer怎么还是在那儿呢?怎么没有自动往下走呢?footer说——我不给绝对主义者让位!
其实这与footer无关,而是因为container对sidebar的无视造成的——你再长,我还是没感觉。
看来这种定位方式只能满足sidebar自己,但对它的兄弟们却毫无益处。
float与margin齐上阵
经过前面的教训,我们重新确立了这个自适应宽度布局必须要达成的条件:
1.sidebar宽度固定,main宽度自适应2.main要在sidebar之前3.后面的元素要能正常显示,不能受影响
由于绝对定位会让其他元素无视它的存在,所以绝对定位的方式必须抛弃。
如果main和sidebar一样,都用float,那main的自适应宽度就没戏了;如果不给main加float,那sidebar又会跑到下一行去。
所以,最终我决定:float与margin都用。
我打算把main的宽度设为100%,然后设置float:left,最后把它向左移动320,以便于sidebar能挤上来。
但这么一来main里面的内容也会跟着左移320像素,导致被遮住了,所以我们要把它重新挤出来。为了好挤,我用了一个额外的div包裹住内容,所以html结构变成了这种样子:
<div class="container">
<div class="main">
<div class="main_container">主体内容显示区域</div>
</div>
<div class="sidebar">导航区域</div>
</div
css则变成这样:
.main {
float: left;
width: 100%;
margin-left: -320px;
}
.main_container {
margin-left: 320px;
}
.sidebar {
float: right;
width: 300px;
}
这样一改,真正的“main”就变成了main_container,它的宽度跟以前的main一样,是100%-320。
大家可能注意到了代码中的两个margin-left,一个-320px一个320px,最后结合起来相当于什么都没干,着实蛋疼。但它确实解决了main与sidebar的顺序问题。
这个方法的缺点就是:太怪异,以及额外多了一层div。
display:table
当然,以不折腾人为标准的w3c标准早就为我们提供了制作这种自适应宽度的标准方法。那就简单了:把container设为display:table并指定宽度100%,然后把main+sidebar设为display:table-cell;然后只给sidebar指定一个宽度,那么main的宽度就变成自适应了。
.container {
display: table;
width: 100%;
}
.main {
display: table-cell;
}
.sidebar {
display: table-cell;
width: 300px;
}
display:inline-block
#aside{
width: 300px;
height: 200px;
background-color: red;
display: inline-block;
vertical-align: top;
}
#main{
height: 200px;
width: calc(100% - 400px)
background-color: blue;
display: inline-block;
vertical-align: top;
}
由于是inlineblock所以设置main的width值时要要设置为100%-(aside的宽度+inlineblock的距离+间距)
// inline-block的距离一般很小,也可以在写代码时去除
见:http://www.zhangxinxu.com/wordpress/2012/04/inline-block-space-remove-%E5%8E%BB%E9%99%A4%E9%97%B4%E8%B7%9D/
两个盒子会因为高度不一样而出现在底部对齐,所以要每个加上verical-align:top
创建BFC法
创建一个新的BFC(块级格式化上下文)来防止文字环绕的原理来实现的。BFC就是一个相对独立的布局环境,它内部元素的布局不受外面布局的影响。它可以通过以下任何一种方式来创建:
1.float的值不为none
2.position的值不为static或者relative
3.display的值为 table-cell, table-caption, inline-block, flex, 或者 inline-flex中的其中一个
4.overflow的值不为visible
关于BFC,在w3c里是这样描述的:在BFC中,每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式化时,则为右边框紧挨)。即使在浮动里也是这样的(尽管一个包含块的边框会因为浮动而萎缩),除非这个包含块的内部创建了一个新的BFC。这样,当我们给右侧的元素单独创建一个BFC时,它将不会紧贴在包含块的左边框,而是紧贴在左元素的右边框。
.aside {
float: left;
height: 100px;
width: 300px;
background-color: blue;
}
.main{
overflow: auto;
height: 200px;
background-color: red;
}
flex
#container{
display:flex;/*设为伸缩容器*/
}
#aside{
width:200px;
height: 300px;
background:red;
}
#mian{
height: 500px;
flex:1;/*这里设置为占比1,填充满剩余空间*/
background:blue;
}
flex大法好,注意兼容性
Grid
。。。
多列布局(Multi-column)
。。。
CSS清除浮动
现代Clearfix解决方案
Container with overflow: auto
<div style="overflow: auto;">
<img
style="float: right;"
src="path/to/floated-element.png"
width="500"
height="500"
>
<p>Your content here…</p>
</div>
Clearfix Reloaded
大多数现代浏览器都使用这个
.container::after {
content: "";
display: block;
clear: both;
}
"Beat That ClearFix", a clearfix for modern browsers
不支持IE6/7
.container::after {
content: "";
display: table;
clear: both;
}
Micro Clearfix
支持Firefox 3.5+, Safari 4+, Chrome, Opera 9+, IE 6+
.container::before, .container::after {
content: "";
display: table;
}
.container::after {
clear: both;
}
.container {
zoom: 1;
}
vue生命周期
Vue生命周期
- 每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们自己的代码。
生命周期
钩子函数
beforeCreate
- 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
created
- 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
- 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
- el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
beforeUpdate
- 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
-
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
-
该钩子在服务器端渲染期间不被调用。
beforeDestroy
- 实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed
- Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
Vue.nextTick
- 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
Vue.nextTick(function () {
// DOM 更新了
})
- 官方还提供了一种写法,vm.$nextTick,用 this 自动绑定到调用它的实例上
created() {
setTimeout(() => {
this.number = 100
this.$nextTick(() => {
console.log('nextTick', document.getElementsByTagName('p')[0])
})
},100)
}
- 什么时候需要到Vue.nextTick()?
-
- 在 Vue 生命周期的 created() 钩子函数进行的 DOM 操作一定要放在 Vue.nextTick() 的回调函数中。原因是什么呢,原因是在 created() 钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick() 的回调函数中。与之对应的就是 mounted 钩子函数,因为该钩子函数执行时所有的 DOM 挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
-
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的 DOM 结构的时候,这个操作都应该放进 Vue.nextTick() 的回调函数中。
生命周期小结
生命周期钩子的一些使用方法:
- beforecreate : 可以在这加个loading事件,在加载实例时触发
- created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
- mounted : 挂载元素,获取到DOM节点
- updated : 如果对数据统一处理,在这里写上相应函数
- beforeDestroy : 可以做一个确认停止事件的确认框
- nextTick : 更新数据后立即操作dom
更多
CSS居中决策树
CSS居中决策树
一、水平
- 是内联的元素还是类内联元素(比如文本或链接)?
在一个块状元素内居中只要给父元素加:
.center-children {
text-align: center;
}
- 是一个块级元素吗?
你可以通过给块级元素 的margin-left 和 margin-right 设置auto (但他的宽度必须设置好 ,否则它将全宽,不需要居中)
.center-me {
margin: 0 auto;
}
- 是多个块级元素吗?
如果你有两个或两个以上的块级元素需要水平居中在一行 ,那可能你就会需要另一种display方式inline-block了,外加flex
除非你的意思是你有多个块级元素堆叠在彼此之上,给每个元素设置margin:0 auto;就行啦
二、垂直
是内联的元素还是类内联元素(比如文本或链接)
- 一行吗?
有时内联/文本元素可以出现垂直居中,只是因为他们用padding填充上方和下方。
.link {
padding-top: 30px;
padding-bottom: 30px;
}
如果因为某种原因padding不能用,你想居中一些你知道不会换行的文本你可以设置他的line-height等于height
.center-text-trick {
height: 100px;
line-height: 100px;
white-space: nowrap;
}
- 多行吗?
设置上下padding也能给多行文本居中的效果,但如果不行的话。可能这个文本在table表格中。那么vertical-align可能会搞定他
.center-table p {
display: table-cell;
margin: 0;
background: black;
color: white;
padding: 20px;
border: 10px solid white;
vertical-align: middle;
}
能用flexbox吗?
.flex-center-vertically {
display: flex;
justify-content: center;
flex-direction: column;
height: 400px;
}
注意,以上两种都要求父盒子有固定的高度
如果没有的话可以使用“Ghost Element”技术
.ghost-center {
position: relative;
}
.ghost-center::before {
content: " ";
display: inline-block;
height: 100%;
width: 1%;
vertical-align: middle;
}
.ghost-center p {
display: inline-block;
vertical-align: middle;
}
是一个块级元素吗?
- 知道高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px; /* account for padding and border if not using box-sizing: border-box; */
}
- 不知道高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
- 可以用flexbox
.parent {
display: flex;
flex-direction: column;
justify-content: center;
}
三、水平和垂直
- 固定宽度和高度的元素吗?
.parent {
position: relative;
}
.child {
width: 300px;
height: 100px;
padding: 20px;
position: absolute;
top: 50%;
left: 50%;
margin: -70px 0 0 -170px;
}
- 不固定宽度和高度的元素吗?
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
- 可以使用flexbox吗?
.parent {
display: flex;
justify-content: center;
align-items: center;
}
- 可以使用grid吗?
body, html {
height: 100%;
display: grid;
}
span { /* thing to center */
margin: auto;
}
CSS隐藏
CSS隐藏
CSS元素隐藏
在CSS中,让元素隐藏(指屏幕范围内肉眼不可见)的方法很多,有的占据空间,有的不占据空间; 有的可以响应点击,有的不能响应点击。一个一个看。
代码如下:
{
display: none;
/* 不占据空间,无法点击 */
}
{
visibility: hidden;
/* 占据空间,无法点击 */
}
{
position: absolute;
top: -999em;
/* 不占据空间,无法点击 */
}
{
position: relative;
top: -999em;
/* 占据空间,无法点击 */
}
{
position: absolute;
visibility: hidden;
/* 不占据空间,无法点击 */
}
{
height: 0;
overflow: hidden;
/* 不占据空间,无法点击 */
}
{
opacity: 0;
filter: Alpha(opacity=0);
/* 占据空间,可以点击 */
}
{
position: absolute;
opacity: 0;
filter: Alpha(opacity=0);
/* 不占据空间,可以点击 */
}
{
zoom: 0.001;
-moz-transform: scale(0);
-webkit-transform: scale(0);
-o-transform: scale(0);
transform: scale(0);
/* IE6/IE7/IE9不占据空间,IE8/FireFox/Chrome/Opera占据空间。都无法点击 */
}
{
position: absolute;
zoom: 0.001;
-moz-transform: scale(0);
-webkit-transform: scale(0);
-o-transform: scale(0);
transform: scale(0);
/* 不占据空间,无法点击 */
}
display:none和visibility:hidden
目前,我所知道的不同有三点(欢迎补充):
-
空间占据(display:none不占据空间,visibility:hidden仍占据空间。)
-
回流与渲染(display:none隐藏产生reflow和repaint(回流与重绘),而visibility:hidden没有这个影响前端性能的问题。)
-
株连性 所谓“株连性”,就是如果祖先元素遭遇某祸害,则其子子孙孙无一例外也要遭殃。display:none就是“株连性”明显的声明:一旦父节点元素应用了display:none,父节点及其子孙节点元素全部不可见,而且无论其子孙元素如何不屈地挣扎都无济于事。
在实际的web应用中,我们要经常实现一些显示隐藏的功能,由于display:none本身特性以及jQuery潜在的驱动,使得我们对display:none这种隐藏特性相当熟知。因此,久而久之会形成比较牢固的情感化认识,并无法避免地将这种认识迁移到其他类似表现属性(eg. visibility)的认识上,再加上一些常规经验……
举例来说吧,通常情况下,我们给一个父元素应用visibility:hidden,则其子孙后代也都会全部不可见。于是,我们就会有类似的认识迁移:应用了visibility:hidden声明下的子孙元素如何不屈地挣扎都摆脱不了不可见被抹杀的命运。而实际上却存在隐藏“失效”的情况。
何时隐藏“失效”?很简单,如果子孙元素应用了visibility:visible,那么这个子孙元素又会刘谦般地显现出来。
visibility就是这样一个funny的属性。
隐藏文本
隐藏网页元素的方法有很多,比如设置display:none,或是使用全透明(opacity)。在设置文本的时候,有时并不希望文本丢失,而通常是把文字转移到屏幕外面,浏览器是可以检测到的。
有如下两种隐藏文本的方式:
- 使用text-indent隐藏:图片替换文本、搜索引擎优化
使用text-indent在h1上设置logo为背景并设置居中来做SEO:
h1 {
text-indent: -9999px;
/*缩进*/
margin: 0auto;
width: 100px;
height: 100px;
/*居中*/
background: url("img/sf.jpg") no-repeat;
}
- 使用position进行定位隐藏:利于屏幕讲述工具的阅读
使用定位
p {
position: absolute;
top: -9999px;
left: -9999px;
}
rgba和opacity
rgba()和opacity都能实现透明效果,但最大的不同是:
-
opacity作用于元素,以及元素内的所有内容的透明度
-
rgba()只作用于元素的颜色或其背景色。(设置rgba透明的元素的子元素不会继承透明效果!)
对比总结:
display:none是个相当惨无人道的声明,子孙后代全部搞死(株连性),而且连块安葬的地方都不留(不留空间),导致全体民众哗然(渲染与回流)。
visibility:hidden则具有人道主义关怀,虽然不得已搞死子孙,但是子孙可以通过一定手段避免(伪株连性),而且死后全尸,墓地俱全(占据空间),国内民众比较淡然(无渲染与回流)。
vue实例
Vue 实例
- 在文档中经常会使用 vm 这个变量名表示 Vue 实例,在实例化 Vue 时,需要传入一个选项对象,它可以包含数据(data)、模板(template)、挂载元素(el)、方法(methods)、生命周期钩子(lifecyclehook)等选项。
data
- Vue 实例的数据都保存在 data 对象中,Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。
let vm = new Vue({
data: {
a;1
}
})
vm.a // -> 1
vm.$data // data
- 这样数据就绑定在 HTML 中,Vue 框架监视 data 的数据变化,自动更新 HTML 内容。
methods
- methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。
let vm = new Vue({
data: { a: 1 },
methods: {
plus: function () {
this.a++
}
}
})
vm.plus()
vm.a // 2
computed
- 计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue
let vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取,值只须为函数
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // -> 2
vm.aPlus = 3
vm.a // -> 2
vm.aDouble // -> 4
watch
- 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
- vue实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
let vm = new Vue({
data: {
a: 1,
b: 2,
c: 3
},
watch: {
// 监控a变量变化的时候,自动执行此函数
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 深度 watcher
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
}
}
})
vm.a = 2 // -> new: 2, old: 1
watch和computed区别
-
从属性名上,computed是计算属性,也就是依赖其它的属性计算所得出最后的值.watch是去监听一个值的变化,然后执行相对应的函数。
-
从实现上,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算。watch在每次监听的值变化时,都会执行回调。其实从这一点来看,都是在依赖的值变化之后,去执行回调。很多功能本来就很多属性都可以用,只不过有更适合的。如果一个值依赖多个属性(多对一),用computed肯定是更加方便的。如果一个值变化后会引起一系列操作,或者一个值变化会引起一系列值的变化(一对多),用watch更加方便一些。
-
watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作。computed通常就是简单的计算。
-
watch和computed并没有哪个更底层,watch内部调用的是vm.$watch,它们的共同之处就是每个定义的属性都单独建立了一个Watcher对象。
filiters
-
过滤器本质就是数据在呈现之前先进行过滤和筛选。
-
Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。过滤器应该被添加在 mustache 插值的尾部,由“管道符”指示:
<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:id="rawId | formatId"></div>
Vue 2.x 中,过滤器只能在 mustache 绑定和 v-bind 表达式(从 2.1.0 开始支持)中使用,因为过滤器设计目的就是用于文本转换。为了在其他指令中实现更复杂的数据变换,你应该使用计算属性。
过滤器函数总接受表达式的值作为第一个参数。
new Vue({
// ...
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
过滤器可以串联:
{{ message | filterA | filterB }}
过滤器是 JavaScript 函数,因此可以接受参数:
{{ message | filterA('arg1', arg2) }}
这里,字符串 'arg1' 将传给过滤器作为第二个参数, arg2 表达式的值将被求值然后传给过滤器作为第三个参数。
HTML
HTML
超文本标记语言(英语:HyperTextMarkupLanguage,简称:HTML)是一种用于创建网页的标准标记语言。
HTML语义化
- 语义化的含义就是用正确的标签做正确的事情,html语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;在没有样式CCS情况下也以一种文档格式显示,并且是容易阅读的。搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
DOCTYPE和浏览器渲染模式
- 文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档。Doctype还会对浏览器的渲染模式产生影响,不同的渲染模式会影响到浏览器对于 CSS 代码甚至 JavaScript 脚本的解析,所以Doctype是非常关键的,尤其是在 IE 系列浏览器中,由DOCTYPE 所决定的 HTML 页面的渲染模式至关重要。
浏览器解析HTML方式
有三种解析方式:
- 非怪异(标准)模式
- 怪异模式
- 部分怪异(近乎标准)模式
在“标准模式”(standards mode) 页面按照 HTML 与 CSS 的定义渲染,而在“怪异模式(quirks mode) 模式”中则尝试模拟更旧的浏览器的行为。 一些浏览器(例如,那些基于 Mozilla 的 Gecko 渲染引擎的,或者 Internet Explorer 8 在 strict mode 下)也使用一种尝试于这两者之间妥协的“近乎标准”(almost standards) 模式,实施了一种表单元格尺寸的怪异行为,除此之外符合标准定义。
一个不含任何 DOCTYPE 的网页将会以 怪异(quirks) 模式渲染。
HTML5提供的是标准模式,向后兼容的, 等同于开启了标准模式,那么浏览器就得老老实实的按照W3C的 标准解析渲染页面,这样一来,你的页面在所有的浏览器里显示的就都是一个样子了。
HTML 元素参考
<meta>
概要
标签提供关于HTML文档的元数据。元数据不会显示在页面上,但是对于机器是可读的。它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务。
常见meta:
页面关键词
<meta name="keywords" content="your tags" >
页面描述
<meta name="description" content="150 words" />
搜索引擎索引方式
<meta name="robots" content="index,follow" />
<!--
all:文件将被检索,且页面上的链接可以被查询;
none:文件将不被检索,且页面上的链接不可以被查询;
index:文件将被检索;
follow:页面上的链接可以被查询;
noindex:文件将不被检索;
nofollow:页面上的链接不可以被查询。
-->
页面重定向和刷新
<meta http-equiv="refresh" content="0;url=" />
其他
<meta name="author" content="author name" /> <!-- 定义网页作者 -->
<meta name="google" content="index,follow" />
<meta name="googlebot" content="index,follow" />
<meta name="verify" content="index,follow" />
移动设备
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no"/>
<!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 -->
WebApp全屏模式
<meta name="apple-mobile-web-app-capable" content="yes" /> <!-- 启用 WebApp 全屏模式 -->
隐藏状态栏/设置状态栏颜色
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
添加到主屏后的标题
<meta name="apple-mobile-web-app-title" content="标题">
忽略数字自动识别为电话号码
<meta content="telephone=no" name="format-detection" />
忽略识别邮箱
<meta content="email=no" name="format-detection" />
申明编码
<meta charset='utf-8' />
优先使用 IE 最新版本和 Chrome
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<!-- 关于X-UA-Compatible -->
<meta http-equiv="X-UA-Compatible" content="IE=6" ><!-- 使用IE6 -->
<meta http-equiv="X-UA-Compatible" content="IE=7" ><!-- 使用IE7 -->
<meta http-equiv="X-UA-Compatible" content="IE=8" ><!-- 使用IE8 -->
禁止浏览器从本地计算机的缓存中访问页面内容
<meta http-equiv="Pragma" content="no-cache">
浏览器不会自动调整文件的大小,也就是说是固定大小,不会随着浏览器拉伸缩放。
<meta name="MobileOptimized" content="240"/>
<a>
href属性
- 这是一个必需属性为锚定义一个超文本链接来源。这表示链接目标的URL或URL片段。URL片段是由一个hash符号(#),它指定一个内部目标在当前文档中的位置开头的名字。URL不限于网页(HTTP)的文件。URL可能使用浏览器所支持的任何协议。
注意
- 可以使用href="#top"或者href="#"链接返回到页面顶部.
- href=" " 会刷新页面.
- href="javascript:void(0)" 仅仅表示一个死链接,执行空事件.
target属性
该属性指定在何处显示链接的资源。 取值为标签(tab),窗口(window),或框架(iframe)等浏览上下文的名称或其他关键词。以下关键字具有特殊的意义:
_self
- 当前页面加载,即当前的响应到同一HTML 4 frame(或HTML5浏览上下文)。此值是默认的,如果没有指定属性的话。
_blank
- 新窗口打开,即到一个新的未命名的HTML4窗口或HTML5浏览器上下文
_parent
- 加载响应到当前框架的HTML4父框架或当前的HTML5浏览上下文的父浏览上下文。如果没有parent框架或者浏览上下文,此选项的行为方式相同_self。
_top
- HTML4中:加载的响应成完整的,原来的窗口,取消所有其它frame。
- HTML5中:加载响应进入顶层浏览上下文(即,浏览上下文,它是当前的一个的祖先,并且没有parent)。如果没有parent框架或者浏览上下文,此选项的行为方式相同_self。
<form>
属性
action
一个处理这个form信息的程序所在的URL。
method
浏览器使用这种 HTTP 方式来提交 form. 可能的值有:
-
post:指的是 HTTP POST 方法 ; 表单数据会包含在表单体内然后发送给服务器.
-
get: 指的是 HTTP GET 方法; 表单数据会附加在 URI action属性中并以 '?' 作为分隔符, 然后这样得到的 URI 再发送给服务器. 当这样做(数据暴露在URI里面)没什么副作用,或者表单仅包含ASCII字符时,再使用这种方法吧。
例子
<!-- 一个简单的表单,这个表单会发送一个 GET 请求 -->
<form action="">
<label for="GET-name">Name:</label>
<input id="GET-name" type="text" name="name">
<input type="submit" value="Save">
</form>
<!-- 一个简单的表单,发送 POST 请求 -->
<form action="" method="post">
<label for="POST-name">Name:</label>
<input id="POST-name" type="text" name="name">
<input type="submit" value="Save">
</form>
<!-- 使用 fieldset, legend, and label 的表单 -->
<form action="" method="post">
<fieldset>
<legend>Title</legend>
<input type="radio" name="radio" id="radio"> <label for="radio">Click me</label>
</fieldset>
</form>
vue基础
VUE
- vue
vue 指令
- vue指令
- 自定义指令
v-model的简单实现
<input type="text" id="input">
<script>
let i = document.querySelector('#input');
let obj = {};
let temp = {};
Object.defineProperty(obj,'name',{
get(){ // 取obj值时触发
return temp.name;
},
set(val){ //设置obj值时触发,且会调用get
temp.name = val;
i.value = val;
}
})
i.addEventListener('input',function(){
obj.name = this.value;
})
</script>
这里加了temp变量是因为如果直接给obj设置值的话代码会写为
set(val){
obj.name = val
}
obj.name本质就是调用set方法,从而导致循环调用所以要加个temp临时变量。
vue 的生命周期
- 生命周期
- 钩子函数
beforeCreate
- 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
created
- 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
- 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
- el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
beforeUpdate
- 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
-
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
-
该钩子在服务器端渲染期间不被调用。
beforeDestroy
- 实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed
- Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
vue API
CSS
CSS
1.引入
1.内联式
2.style标签
3.link标签
4.import // 在css文件中@import url('文件名')
2.权重
元素, 伪元素: (0,0,0,1)
类, 伪类, 属性: (0,0,1,0)
ID: (0,1,0,0)
内联样式: (1,0,0,0)
//注:继承的权值最低,可算作0.1
!import 最高。大于内联但一般不用;
3.BFC
一、什么是BFC(block formatting context):
- 简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。** 中文常译为块级格式化上下文。是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
在进行盒子元素布局的时候,BFC提供了一个环境,在这个环境中按照一定规则进行布局不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。 也就是说,如果一个元素符合了成为BFC的条件,该元素内部元素的布局和定位就和外部元素互不影响(除非内部的盒子建立了新的 BFC),是一个隔离了的独立容器。(在 CSS3 中,BFC 叫做 Flow Root)
二、 形成 BFC 的条件:
- 浮动元素,float 除 none 以外的值;
- 绝对定位元素,position(absolute,fixed);
- display 为以下其中之一的值 inline-blocks,table-cells,table-captions;
- overflow 除了 visible 以外的值(hidden,auto,scroll);
三、BFC布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
四、BFC常见作用
-
包含浮动元素 问题案例:高度塌陷问题:在通常情况下父元素的高度会被子元素撑开,而在这里因为其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合。这时就可以用bfc来清除浮动了。
-
不被浮动元素覆盖 问题案例: div浮动兄弟遮盖问题:由于左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给蓝色块加 overflow: hidden,触发bfc来解决遮挡问题。
-
BFC 会阻止外边距折叠** 问题案例:margin塌陷问题:在标准文档流中,块级标签之间竖直方向的margin会以大的为准,这就是margin的塌陷现象。可以用overflow:hidden产生bfc来解决。
详见
http://www.w3cplus.com/css/understanding-block-formatting-contexts-in-css.html
http://www.zhangxinxu.com/wordpress/2015/02/css-deep-understand-flow-bfc-column-two-auto-layout/
http://www.cnblogs.com/lhb25/p/inside-block-formatting-ontext.html
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.