GithubHelp home page GithubHelp logo

blog's People

Contributors

chesterbu avatar

Stargazers

 avatar

Watchers

 avatar  avatar

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 追踪依赖,在属性被访问和修改时通知变化。

mvvm

  • 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中对象的链可以非常复杂。
一图胜千言。这里借两张图。

prototype
prototype2

简而言之

  • 函数对象,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内部结构图

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谁更长,都不会对布局造成影响。

image.png

但实际上这个方法有个很老火的限制——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。

image.png

咦,好像不对,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;
}

图片
代码很少,而且不会有额外标签。不过这是IE7都无效的方法。

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-leftmargin-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

目前,我所知道的不同有三点(欢迎补充):

  1. 空间占据(display:none不占据空间,visibility:hidden仍占据空间。)

  2. 回流与渲染(display:none隐藏产生reflow和repaint(回流与重绘),而visibility:hidden没有这个影响前端性能的问题。)

  3. 株连性 所谓“株连性”,就是如果祖先元素遭遇某祸害,则其子子孙孙无一例外也要遭殃。display:none就是“株连性”明显的声明:一旦父节点元素应用了display:none,父节点及其子孙节点元素全部不可见,而且无论其子孙元素如何不屈地挣扎都无济于事。

在实际的web应用中,我们要经常实现一些显示隐藏的功能,由于display:none本身特性以及jQuery潜在的驱动,使得我们对display:none这种隐藏特性相当熟知。因此,久而久之会形成比较牢固的情感化认识,并无法避免地将这种认识迁移到其他类似表现属性(eg. visibility)的认识上,再加上一些常规经验……

举例来说吧,通常情况下,我们给一个父元素应用visibility:hidden,则其子孙后代也都会全部不可见。于是,我们就会有类似的认识迁移:应用了visibility:hidden声明下的子孙元素如何不屈地挣扎都摆脱不了不可见被抹杀的命运。而实际上却存在隐藏“失效”的情况。

何时隐藏“失效”?很简单,如果子孙元素应用了visibility:visible,那么这个子孙元素又会刘谦般地显现出来。

visibility就是这样一个funny的属性。

隐藏文本

隐藏网页元素的方法有很多,比如设置display:none,或是使用全透明(opacity)。在设置文本的时候,有时并不希望文本丢失,而通常是把文字转移到屏幕外面,浏览器是可以检测到的。

有如下两种隐藏文本的方式:

  1. 使用text-indent隐藏:图片替换文本、搜索引擎优化
使用text-indenth1上设置logo为背景并设置居中来做SEOh1 {
    text-indent: -9999px;
    /*缩进*/
    margin: 0auto;
    width: 100px;
    height: 100px;
    /*居中*/
    background: url("img/sf.jpg") no-repeat;
}
  1. 使用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对象。

  • 更多:* 谈Vue的依赖追踪系统 ——搞懂methods watch和compute的区别和联系

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可能使用浏览器所支持的任何协议。
注意
  1. 可以使用href="#top"或者href="#"链接返回到页面顶部.
  2. href=" " 会刷新页面.
  3. 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. 可能的值有:

  1. post:指的是 HTTP POST 方法 ; 表单数据会包含在表单体内然后发送给服务器.

  2. 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

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 的条件:

  1. 浮动元素,float 除 none 以外的值;
  2. 绝对定位元素,position(absolute,fixed);
  3. display 为以下其中之一的值 inline-blocks,table-cells,table-captions;
  4. overflow 除了 visible 以外的值(hidden,auto,scroll);

三、BFC布局规则

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  3. 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC的区域不会与float box重叠。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算BFC的高度时,浮动元素也参与计算

四、BFC常见作用

  1. 包含浮动元素 问题案例:高度塌陷问题:在通常情况下父元素的高度会被子元素撑开,而在这里因为其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合。这时就可以用bfc来清除浮动了。 这里写图片描述

  2. 不被浮动元素覆盖 问题案例: div浮动兄弟遮盖问题:由于左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给蓝色块加 overflow: hidden,触发bfc来解决遮挡问题。 这里写图片描述

  3. 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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.