diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ee1622 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/* +*.iml \ No newline at end of file diff --git "a/2017/03/01/Angular\345\256\236\346\227\266\347\233\221\346\216\247/index.html" "b/2017/03/01/Angular\345\256\236\346\227\266\347\233\221\346\216\247/index.html" deleted file mode 100644 index eecc595..0000000 --- "a/2017/03/01/Angular\345\256\236\346\227\266\347\233\221\346\216\247/index.html" +++ /dev/null @@ -1,74 +0,0 @@ - - - - -
- - - -prototype是函数的属性
- _proto_是对象的属性
- 函数也是对象,所以函数两者都有
-_proto_是对象的属性,在JS中一切都是对象,所以会形成一条链,递归访问最终到头,最终为null,
-当JS引擎查找对象的属性时,会先查找对象本身,之后顺着原型连向上查找
-闭包就是能够读取其他函数内部变量的函数,闭包就是将函数内部和函数外部连接起来的一座桥梁
- function f(){
- var n=0;
- function d(){
- console.log(n);
- }
- return n;
- }
-
-闭包作用:1.读取函数内部变量;2.变量值不被回收,始终放在内存;
-注意点:便面过多使用,以免内存溢出
-1.事件捕捉阶段:事件开始由顶层对象触发,然后逐级向下传播,直到目标的元素;
- 2.处于目标阶段:处在绑定事件的元素上;
- 3.事件冒泡阶段:事件由具体的元素先接收,然后逐级向上传播,直到不具体的元素;
-阻止冒泡行为及默认行为
-IE:event.cancelBubble=true; event.returnValue=false;
-非IE:event.stopPropagation();event.preventDefault();
-了解了事件流,那么就不难理解事件委托,我们的DOM是有层级的,例如ul > n*li事件委托就是当点击子元素的时候,利用事件流机制
-将子元素的操作委托到父元素来代理,用target判断具体的触发位置
- someDom.addEventListener('click',function(ev){
- console.log('当前点击区域为'+target.tagName);
- })
-三者均用于改变当前执行环境的this指向,call和apply参数列表不同,两者均为立即执行,bind可非立即调用
-bind可将多个参数的函数变成只带一个参数的函数
-a.call(a,b,c); a.apply(a,[b,c]);
-var sum = function(x,y) { return x + y };
-var succ = sum.bind(null, 1);
-succ(2);
-三点 ip:host:port
-同源策略是有限制的,但是我们却可以调用非本域名的script脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用
-某个函数的js代码,在src中进行了调用,这样实现了跨域
-JavaScript是单线的,这一点我相信大家都知道,那么只能在一条线程上执行,是如何实现异步的呢,我们来
了解一下Js的执行机制
1.JS首先判断操作是否同步,同步继续执行,异步则进入event table
- 2.异步任务在event table中注册函数,当满足触发条件后,任务被推入event queue
- 3.同步任务一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主进程中
-异步任务还分为宏任务(I/O,setTimeout,setInterval,setImmediate)和微任务(Promise,process.nextTick)
- -先了解一个这样的问题,Javascript在整个运行时都可以被重写
-Angular2启动的时候会对浏览器API打低级补丁,例如AddEventListener(),会覆盖原有的方法,对原有方法进行扩展
-这样才有机会进行更改检测,并做相关处理,对于浏览器的低级API补丁,Angular2采用Zonejs来完成,这是一种通用
-的机制,我们可以为浏览器添加额外的功能,Angular2内部使用Zone来触发更改机制,还有一种可能是执行应用程序
-分析,或跟踪多个虚拟机的堆栈信息进行跟踪
- ZoneJS对浏览器所有基础事件进行了补丁,timeOut,interval,Ajax,click,hover等等,但是它是有限制的,因为zonejs不
-支持异步浏览器API,例如indexDB的回调,这样就解释了为什么他的变化会被检测到
-Angular2启动的时候,每一个组件都有一个关联的更改检测器
-1.缺省的变更机制
- 对于模板中使用的表达式,现有值与原来的值进行比较,默认情况的检查不会做深度对比,仅仅会对使用的属性进行对比
-2.changeDetection.OnPush && Immutable.js类似库
- 此种情况下引用的变更才会触发,而属性的改变不会触发,这样的检查显然是不靠谱的,所以引入了Immutable.js,来确保
-对象的不可变性,同时Angular2采用的是单向的数据流,这样就避免了angular1的双向绑定那个三重的for循环,进而提升了
-性能,Angular2的dev和生产模式下也是不同的,对于检查,在生产环境只会检查一次
-1 | constructor(private ref:ChangeDetectorRef){ |
Angular2和angular1的默认检查还是有很大不同的,做了一些优化,而且在Angular2中,变化检测是可以选择的
-
- 我们常用的浏览器由以下几个部分组成
-用户界面:地址栏,书签栏...简单说就是除了请求页面之外的内容
- 浏览器引擎:协调UI和渲染引擎
- 渲染引擎:展示请求内容
- 网络组件:负责网络调用
- UI后端:绘制基本UI组件
- JavaScript解析器:解析和执行JavaScript代码
- 数据存储:浏览器的本地存储
-简单来说分为五部 loading->parsing->rending->Layout>painting
-loading指浏览器的加载顺序,它起始于navigationStart,终止于loadEventEnd
-1.首先浏览器会判断,你是如何到达当前页面的,是重定向还是直接加载
- if(unload) unloadStart->unloadEnd
- if(redirect) redirectStart->redirectEnd
- 2.接下来浏览器会开始发起资源请求,首先判断是否有缓存,如果没有要做DNS解析查询
- fetchStart: cache ? cache : domainLookupStart->domainLookupEnd
- 3.接下来使用解析的地址来建立TCP连接,发起http请求,等候资源
- domain:connectStart->connectEnd,requestStart->responseStart
- 4.有了资源那么就开始加载DOM,直到DOM加载完毕
- resource:DomLoading->DomContentLoaded
-parsing是浏览器将HTML文档转换为DOM树并下载资源的过程
-HTML解析器的任务是将HTML标记解析成解析树,解析树是由DOM元素和属性节点构成的树结构,根节点是为Document
- 解析主要包括两个部分:标记化和树的构建
- (1)标记化:标记化是词法分析过程,将输入内容解析成多个标记
- (2)树的构建:在创建解析器的同时,也会创建Document对象。在树构建阶段,以Document为根节点的DOM树也会不断进行修改,添加
- 各种元素。标记生成器发送的每个节点都会由树构建器进行处理。每个标记都有对应的DOM元素,这些元素会在接收到标记时创建
- <html> --> <head> --> </head> --> <body> --> </body> -- </html>
-
- 在HTML解析器解析HTML的同时,CSS 解析器会构建CSS规则树
-在 DOM 树构建的同时,浏览器还会构建呈现树。这是由可视化元素按照其显示顺序而组成的树,也是文档的可视
化表示.呈现器是和 DOM 元素相对应的,但并非一一对应。非可视化的 DOM 元素不会插入呈现树中
这此阶段会发生重绘和回流
- 重绘:css属性改变,尺寸不变
- 回流:尺寸改变,虽然浏览器会异步增量回流,但是消耗也是很大的,所以成本特别高
-Layout是计算页面上具体的展示位置
-rending时呈现树构建完毕,此时并不包含位置和大小信息,计算这些值的过程就是布局.HTML 采用基于流的布局模型,这意味着大多
-数情况下只要一次遍历就能计算出几何信息。处于流中靠后位置元素通常不会影响靠前位置元素的几何特征,因此布局可以按从左至
-右、从上至下的顺序遍历文档。
-painting才是最终的绘制页面
-在绘制过程中,图形处理层可能使用通用CPU,也可能使用图形处理器GPU,当使用GPU用于图形渲染时,图形驱动软件会把任务分成多个
-部分,这样可以充分利用GPU的并行计算,用于在渲染过程中进行大量的浮点计算。
-(1)渲染引擎把HTML文档解析成DOM树,把标签转换成DOM节点。
- (2)解析文档的同时,渲染引擎会把样式解析成CSS规则树
- (3)渲染器是在文档解析和创建DOM节点后创建的,会计算DOM节点的样式信息(display:none除外),渲染树的节点。DOM树和CSS规则
- 树结合之后,形成了Style Content Tree,将其和渲染树关联,就完成了渲染树。
- (4)渲染树构建出来之后,就进入布局阶段,为渲染树的每个节点分配一个屏幕上的确切坐标。
- (5)最后遍历渲染树,通过用户界面后端将每个节点绘制出来。
-
- Webpack本质是一个Js应用程序的静态模块打包器,它为前端的工程化开发提供了一套相对容易和完整的解决方
案,当webpack处理应用程序的时候,它会递归构建一个依赖关系图,然后进行打包任务
webpack有四个核心概念:entry、output、loader、plugins
entry作为webpack起始的入口,告诉webpack我的应用程序是从何处开始,entry的配置可以一个或多个起点
示例:
// 单入口
- entry: './src/main.js' // 你可以这样
- entry: { main : './src/main.js' } // 你还可以这样
- // 多入口
- entry: { main : './src/main.js', vendors: './src/lib/vendors.js' } // 你可以这样
- entry: { main : './src/main.js', vendors: './src/lib/vendors.js' } // 你还可以这样
-output作为webpack起始的出口,告诉webpack我的应用程序打包后的文件如何安置
示例:
// 分别对应是否多入口打包
- output: { filename : 'app.js', path: './build/assets/js' }
- output: { filename : [name].js, publicPath: '/assets/',path: __dirname + '/build/assets/js' }
- output: { filename : [name].[chunkhash].js, publicPath: '/assets/',path: __dirname + '/build/assets/js' }
-loader用于对模块代码进行转换,如果使用Angular2,采用TypeScript进行编写,那么打包时就需要转为
JavaScript,亦或是我们的代码中采用scss less,那么都需要进行转换
示例:
// 分别对应是否多入口打包
- module: {
- rules: [
- { test: /\.ts$/, use: 'ts-loader' }
- ]
- }
-plugins其实是弥补了一些loader无法完成的事情,比如压缩
示例:
// 分别对应是否多入口打包
- plugins: {
- new webpack.optimize.UglifyJsPlugin()
- }
-这样看起来,是不是webpack很简单,好像没有很难
- -最近因为公司整体业务方向调整,项目组频繁波动 ~ ~ ~ ,经过了慎重的考虑,我们决定要用Vue来代替原有
的Angular2技术栈,我们这些老油条是无所谓的,什么轮子都能跑,但是Angular2不适合新人,学习曲线太陡
峭,不利于新人培养,以此为背景,我将记录下这一段的学习历程
一贯的原则都是先上官网,直接撸,顺便记录下,好做培训官网地址
-<div id="app">{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" @click="resetMessage" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' },
- methods: { resetMessage(){ this.message = '我被点击了';}}
- });
-<div id="app" v-text="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" v-html="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" v-if="message" ></div>
- <div id="app" v-show="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: true }
- });
-<div id="app"><span v-for="m in message" :key="m">{{m}}</span></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: [1,2,3] }
- });
-<input id="app" v-model="message">
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: '' }
- });
-<div id="app" v-once>{{message}}</div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: '不变' }
- });
-<div id="app" v-bind:title = "message">{{message}}</div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'title' }
- });
-<div id="app" v-pre>{{message}}</div>
- <div id="app" v-clock>{{message}}</div>
-
- 最近因为公司整体业务方向调整,项目组频繁波动 ~ ~ ~ ,经过了慎重的考虑,我们决定要用Vue来代替原有
的Angular2技术栈,我们这些老油条是无所谓的,什么轮子都能跑,但是Angular2不适合新人,学习曲线太陡
峭,不利于新人培养,以此为背景,我将记录下这一段的学习历程
一贯的原则都是先上官网,直接撸,顺便记录下,好做培训官网地址
-<div id="app">{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" @click="resetMessage" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' },
- methods: { resetMessage(){ this.message = '我被点击了';}}
- });
-<div id="app" v-text="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" v-html="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'Hi!' }
- });
-<div id="app" v-if="message" ></div>
- <div id="app" v-show="message" ></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: true }
- });
-<div id="app"><span v-for="m in message" :key="m">{{m}}</span></div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: [1,2,3] }
- });
-<input id="app" v-model="message">
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: '' }
- });
-<div id="app" v-once>{{message}}</div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: '不变' }
- });
-<div id="app" v-bind:title = "message">{{message}}</div>
- <div id="appDemo" >{{ message }}</div>
- var app = new Vue({
- el: '#app',
- data: { message: 'title' }
- });
-<div id="app" v-pre>{{message}}</div>
- <div id="app" v-clock>{{message}}</div>
-
- 上一篇是说Vue的指令,那么接下来就要实际搭建一个Vue的项目,可能只有指令貌似不够用,那么接下来,遇到什么
问题解决什么问题就可以了,其实做项目没有那么复杂,最首要的就是思路要清晰,其他的都好办
好像有一套CLI可以用
-官网地址就在这里:Vue-Cli
-npm install -g vue-cli
- vue init webpack myProject
- cd myProject
- npm run dev
-等待的时间不是很长,就这样,一套基础的环境搭建完毕,启动之后打开 http://localhost:8080/ ,发现一个问题,为什
么我的路由多了一个#号,那么是不是可以去掉hash路由,打开路由文件,这东西属于路由范畴的,我没有配置server,
那么它一定是前端路由管理的,我用的是IDEA可以直接点进去,看具体是怎么用的
node_modules -> vue-router ->router.d.ts
- 关注这段代码
- export type RouterMode = "hash" | "history" | "abstract";
- export declare class VueRouter {
- constructor (options?: RouterOptions);
- app: Vue;
- mode: RouterMode;
- currentRoute: Route;
- }
- 解决了,向下边这样写,默认给的路由是hash路由
- export default new Router({
- mode: 'history',
- routes: [
- {
- path: '/',
- name: 'HelloWorld',
- component: HelloWorld
- }]})
-我们新建一个路由,就叫demo,按照上边的规则,可以这样写
-export default new Router({
- mode: 'history',
- routes: [
- { path: '/',name: 'HelloWorld',component: HelloWorld },
- { path: '/demo',name: 'demo',component: Demo }
- ]})
-刚好用到component,那就看看吧
-1 | <template> |
翻译一下,过渡(动画),过渡组(批量动画),这就是动画啊,不多解释了,直接上DEMO,就在刚才我们新建的component下写
-<div class="hello">
- <h1 v-if="msg" @click="show = !show">{{ msg }}</h1>
- <transition name="fade">
- <p v-show="show">hello</p>
- </transition>
-</div>
-<style scoped>
- &.fade-enter-active, &.fade-leave-active
- {transition: all 0.5s ease}
- &.fade-enter, &.fade-leave-active
- { opacity: 0}
- </style>
-<div class="hello">
- <keep-alive include="demo">
- 这里将会缓存名字叫做demo的组件
- </keep-alive>
- </div>
-这个是一个比较好的功能,react中并没有,不过github上边有一个react-slot包,可以拿来用,其实就是一种多态思想,
slot可以提供这样的功能,我使用一个组件,默认我不传递props时候,它会展现一种状态,当我传递props并且
附带我自定义的内容时候,我希望能展示我自定义的内容,如果你学过Angular,那么就是其中的transclusion
<my-input>
- // 我有一个input组件,我期望在我的组件后边附加一个单位
- <template slot="append">美元</template>
- </my-input>
-
- 上一篇是说Vue的指令,那么接下来就要实际搭建一个Vue的项目,可能只有指令貌似不够用,那么接下来,遇到什么
问题解决什么问题就可以了,其实做项目没有那么复杂,最首要的就是思路要清晰,其他的都好办
好像有一套CLI可以用
-官网地址就在这里:Vue-Cli
-npm install -g vue-cli
- vue init webpack myProject
- cd myProject
- npm run dev
-等待的时间不是很长,就这样,一套基础的环境搭建完毕,启动之后打开 http://localhost:8080/ ,发现一个问题,为什
么我的路由多了一个#号,那么是不是可以去掉hash路由,打开路由文件,这东西属于路由范畴的,我没有配置server,
那么它一定是前端路由管理的,我用的是IDEA可以直接点进去,看具体是怎么用的
node_modules -> vue-router ->router.d.ts
- 关注这段代码
- export type RouterMode = "hash" | "history" | "abstract";
- export declare class VueRouter {
- constructor (options?: RouterOptions);
- app: Vue;
- mode: RouterMode;
- currentRoute: Route;
- }
- 解决了,向下边这样写,默认给的路由是hash路由
- export default new Router({
- mode: 'history',
- routes: [
- {
- path: '/',
- name: 'HelloWorld',
- component: HelloWorld
- }]})
-我们新建一个路由,就叫demo,按照上边的规则,可以这样写
-export default new Router({
- mode: 'history',
- routes: [
- { path: '/',name: 'HelloWorld',component: HelloWorld },
- { path: '/demo',name: 'demo',component: Demo }
- ]})
-刚好用到component,那就看看吧
-1 | <template> |
翻译一下,过渡(动画),过渡组(批量动画),这就是动画啊,不多解释了,直接上DEMO,就在刚才我们新建的component下写
-<div class="hello">
- <h1 v-if="msg" @click="show = !show">{{ msg }}</h1>
- <transition name="fade">
- <p v-show="show">hello</p>
- </transition>
-</div>
-<style scoped>
- &.fade-enter-active, &.fade-leave-active
- {transition: all 0.5s ease}
- &.fade-enter, &.fade-leave-active
- { opacity: 0}
- </style>
-<div class="hello">
- <keep-alive include="demo">
- 这里将会缓存名字叫做demo的组件
- </keep-alive>
- </div>
-这个是一个比较好的功能,react中并没有,不过github上边有一个react-slot包,可以拿来用,其实就是一种多态思想,
slot可以提供这样的功能,我使用一个组件,默认我不传递props时候,它会展现一种状态,当我传递props并且
附带我自定义的内容时候,我希望能展示我自定义的内容,如果你学过Angular,那么就是其中的transclusion
<my-input>
- // 我有一个input组件,我期望在我的组件后边附加一个单位
- <template slot="append">美元</template>
- </my-input>
-
- 上一篇是说Vue的内置组件,其中的slot使用的是了Vue实例中的属性,那么接下来我们就认识一下,介绍一个Vue
的实例属性
上次是说这样的一个input组件,我期望在文本后边附加单位,很常见的场景,没有给出具体的实现,那么我们现
在来实现这样的一个组件,可以分发内容
<template>
- <input type="text">
- <span v-if="$slots.append">
- <slot name="append"></slot>
- </span>
- </template>
- <script>
- //为什么可以直接使用$slots,因为它是绑定在Vue实例上的属性 vm.$slots
- //方便我们拿到我们传递的slot属性
- </script>
- <style>
- </style>
-$scopedSlots与之类似,只不过是用来访问作用域slot, $slots可以说更宽泛一些
-这五个实例属性,都是与DOM操作相关的,所以把他们放在一起,这样好记忆也好理解
-<template id="parent">
- <div>
- <child ref="childOne"></child>
- <child ref="childTwo"></child>
- </div>
- </template>
- <script>
- // 查找 一个人的儿子,一种是直接看他的儿子是谁,另一种是看他的下一辈有中有谁的名字是XXX
- // 就这样,在父组件中访问子组件的DOM,有两种方式,
- this.$child[0] === this.$ref.childOne //true
- this.$child[1] === this.$ref.childTwo //true
- // 相同的,找组件的父元素DOM
- this.$parent
- // 同样的,当前组件树的根
- this.$root
- // 同样的,Vue的根DOM元素
- this.$el
- </script>
- <style>
- </style>
-这四个实例主要是用来操作相关的DOM
-$props是组件传入的属性,$data是当前组件使用的初始化数据
-<template>
- <my-input :data="someObj">
-</template>
-<script>
- export default {
- data() {
- this.initializeData = {}
- },
- props:{someObj}
- }
-</script>
-<script>
- // 判断当前实例是否运行在服务器(比如服务端渲染用到)
- this.$isServer
- // Vue实例的初始化选项
- this.$options
-</script>
-这两个是作为创建更高层次的组件时使用
-<script>
- // 父作用域中不作为 prop 被识别 (且获取) 的特性绑定
- this.$attrs
- // 父作用域中的事件监听器
- this.$listeners
- </script>
-
- 上一篇是说Vue的内置组件,其中的slot使用的是了Vue实例中的属性,那么接下来我们就认识一下,介绍一个Vue
的实例属性
上次是说这样的一个input组件,我期望在文本后边附加单位,很常见的场景,没有给出具体的实现,那么我们现
在来实现这样的一个组件,可以分发内容
<template>
- <input type="text">
- <span v-if="$slots.append">
- <slot name="append"></slot>
- </span>
- </template>
- <script>
- //为什么可以直接使用$slots,因为它是绑定在Vue实例上的属性 vm.$slots
- //方便我们拿到我们传递的slot属性
- </script>
- <style>
- </style>
-$scopedSlots与之类似,只不过是用来访问作用域slot, $slots可以说更宽泛一些
-这五个实例属性,都是与DOM操作相关的,所以把他们放在一起,这样好记忆也好理解
-<template id="parent">
- <div>
- <child ref="childOne"></child>
- <child ref="childTwo"></child>
- </div>
- </template>
- <script>
- // 查找 一个人的儿子,一种是直接看他的儿子是谁,另一种是看他的下一辈有中有谁的名字是XXX
- // 就这样,在父组件中访问子组件的DOM,有两种方式,
- this.$child[0] === this.$ref.childOne //true
- this.$child[1] === this.$ref.childTwo //true
- // 相同的,找组件的父元素DOM
- this.$parent
- // 同样的,当前组件树的根
- this.$root
- // 同样的,Vue的根DOM元素
- this.$el
- </script>
- <style>
- </style>
-这四个实例主要是用来操作相关的DOM
-$props是组件传入的属性,$data是当前组件使用的初始化数据
-<template>
- <my-input :data="someObj">
-</template>
-<script>
- export default {
- data() {
- this.initializeData = {}
- },
- props:{someObj}
- }
-</script>
-<script>
- // 判断当前实例是否运行在服务器(比如服务端渲染用到)
- this.$isServer
- // Vue实例的初始化选项
- this.$options
-</script>
-这两个是作为创建更高层次的组件时使用
-<script>
- // 父作用域中不作为 prop 被识别 (且获取) 的特性绑定
- this.$attrs
- // 父作用域中的事件监听器
- this.$listeners
- </script>
-
- 重新认识一下,Vue整个的生命周期,无论学什么框架,都需要了解整个的生命周期,这对于我们的开发是十分重
要的,让我们知道,什么时候可以做什么事
我们的整个Vue应用都是从这里开始的,在这里我们可以选择初始化参数,可以配置相应的路由,可以决定我们在
- 哪个DOM元素上来初始化我们的应用,一个Vue项目就从这里开始,我们将通过几个方法来认识一下Vue
-此时的组件实例刚被创建,我们赋予组件的初始数据,data还没有运行,具体有哪些应用场景,这个才是我关
心的问题,我们以前写JQuery的时候会有这样的一段代码,用来判断是否页面加载完毕,举个栗子:
$(function(){ alert('页面加载完毕')})
- 那么换成Vue了,beforeCreate就做了同样的事情
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,但是DOM还未生成,这个时候就是我们的
create函数所处的阶段,那么此时,我们可以做什么呢,举个栗子:
我们的页面经常需要从后台获取数据,我们会给我们的组件赋一些初始值,等到后续数据载入后替换,那就是这里了
- created(){ setTimeOut(function(){this.initData = { name:1, value:2 }})}
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,但是还没有挂载到具体的
DOM,这个时候就是我们的beforeMount函数所处的阶段,那么此时,我们可以做什么呢,举个栗子:
此时Vue的根DOM元素已经被初始化,在这里,我们拿到我们的虚拟DOM,虽然现在看起来像是占位符
- beforeMount(){
- console.log(this.$el); // <div id="root">{{hello}}</div>
- }
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
这个时候就是我们的mounted函数所处的阶段,需要注意的一点就是,不一定所有的子组件都也都一起被挂载
那么此时,我们可以做什么呢,举个栗子:
此时Vue的根DOM元素已经被初始化,在这里,我们可以拿到真实的DOM
- mounted(){
- console.log(this.$el); // <div id="root">你好</div>
- }
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
在此之后我们的数据发生了变化,有变化还没有及时重新渲染之前,这个时候就是我们的beforeUpdate函数
此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
在此之后我们的数据发生了变化,DOM已经重新渲染之后,这个时候就是我们的updated函数调用的触发点
那么此时,我们可以做什么呢,举个栗子:
我们的页面有这样一个滚动视窗,我们需要知道初始化之后的一个按钮的展示位置,如果超过了某一个height
-那么动态的计算展示窗体的宽高,此时可以封装在这里
-updated(){ this.computeHeight()}
-在第二节中,我们提到了一个内置组件keep-alive,当此组件被激活的时候,会调用改方法
-keep-alive组件被停用的时候,会调用改方法
-此时的组件实例还未被销毁,我们可以利用组件的当前实例做一些操作
-销毁整个Vue实例,回收所有的资源
- -重新认识一下,Vue整个的生命周期,无论学什么框架,都需要了解整个的生命周期,这对于我们的开发是十分重
要的,让我们知道,什么时候可以做什么事
我们的整个Vue应用都是从这里开始的,在这里我们可以选择初始化参数,可以配置相应的路由,可以决定我们在
- 哪个DOM元素上来初始化我们的应用,一个Vue项目就从这里开始,我们将通过几个方法来认识一下Vue
-此时的组件实例刚被创建,我们赋予组件的初始数据,data还没有运行,具体有哪些应用场景,这个才是我关
心的问题,我们以前写JQuery的时候会有这样的一段代码,用来判断是否页面加载完毕,举个栗子:
$(function(){ alert('页面加载完毕')})
- 那么换成Vue了,beforeCreate就做了同样的事情
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,但是DOM还未生成,这个时候就是我们的
create函数所处的阶段,那么此时,我们可以做什么呢,举个栗子:
我们的页面经常需要从后台获取数据,我们会给我们的组件赋一些初始值,等到后续数据载入后替换,那就是这里了
- created(){ setTimeOut(function(){this.initData = { name:1, value:2 }})}
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,但是还没有挂载到具体的
DOM,这个时候就是我们的beforeMount函数所处的阶段,那么此时,我们可以做什么呢,举个栗子:
此时Vue的根DOM元素已经被初始化,在这里,我们拿到我们的虚拟DOM,虽然现在看起来像是占位符
- beforeMount(){
- console.log(this.$el); // <div id="root">{{hello}}</div>
- }
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
这个时候就是我们的mounted函数所处的阶段,需要注意的一点就是,不一定所有的子组件都也都一起被挂载
那么此时,我们可以做什么呢,举个栗子:
此时Vue的根DOM元素已经被初始化,在这里,我们可以拿到真实的DOM
- mounted(){
- console.log(this.$el); // <div id="root">你好</div>
- }
-此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
在此之后我们的数据发生了变化,有变化还没有及时重新渲染之前,这个时候就是我们的beforeUpdate函数
此时的组件实例刚被创建完成,组件实例中的属性已经计算完毕,DOM已经首次生成,已经挂载到具体的DOM,
在此之后我们的数据发生了变化,DOM已经重新渲染之后,这个时候就是我们的updated函数调用的触发点
那么此时,我们可以做什么呢,举个栗子:
我们的页面有这样一个滚动视窗,我们需要知道初始化之后的一个按钮的展示位置,如果超过了某一个height
-那么动态的计算展示窗体的宽高,此时可以封装在这里
-updated(){ this.computeHeight()}
-在第二节中,我们提到了一个内置组件keep-alive,当此组件被激活的时候,会调用改方法
-keep-alive组件被停用的时候,会调用改方法
-此时的组件实例还未被销毁,我们可以利用组件的当前实例做一些操作
-销毁整个Vue实例,回收所有的资源
- -上面几篇介绍了一些基础的概念,但是实际项目中往往会用到更多,接下来会介绍一些项目中会用到的点
-经常我们会遇到这样的情况,当我们操作一个component的时候,我们需要让另外的component知道,我
操作了当前的component,方便后续组件做一些操作,比如:刷新
我们定义component的时候,有时候需要传递一些属性,这样方便我们更好的控制组件,比如说我的组件
是否展示一个DOM区域,那么此时你可能会用到props,这就是父子通信的一种,在父组件中定义一些属性
告诉子组件 ,我需要展示哪些东西,比如:我们的Table组件,需要一个数据源来遍历出表格
<template>
- <div>
- <child-component :data="formData"></child-component>
- </div>
- </template>
- <script>
- created(){
- this.formData=[1,2,3];
- }
- </script>
-为了增加我们的控制力度,我们有时候需要一些操作,我的子组件某一个属性发生变化,我需要让父组件
知道有这么一件事情,比如:当分页组件点击的时候,我需要更新父组件中的Table组件的数据,那么我就
需要去跟父组件之间进行通信,此时你可以这样做,父组件就可以收到子组件的信息,做相关操作
<!-- child-component -->
-<template>
- <div @click=sendMessage>
-
- </div>
- </template>
- <script>
- sendMessage(){
- this.$emit('sendMessage','我被点击')
- }
- </script>
- <!-- parent-component -->
- <template>
- <div>
- <child-component v-on:sendMessage="receiveMessage"></child-component>
- </div>
- </template>
- <script>
- receiveMessage(obj){
- console.log(obj);
- }
- </script>
-其实学会了父子组件的通信,那么兄弟间的通信就水到渠成了,其实就是这样的关系 子 => 父 =>子
-如果你写的多了,那么你应该会觉得有些麻烦,尤其是层级过多的父子组件,这个时候我们有这样的解决方案,
那就是eventhub事件中心,你不需要去在template上绑定事件,只需要发送和接收
//根注册
- data: {
- eventHub: new Vue()
- }
- //发送方
- this.$root.eventHub.$emit('sendMessage', data)
- //接收方
- this.$root.eventHub.$on('sendMessage', Func)
-这里可能会有这样的一个问题,比如说你有两个页面组件的时候,在页面A发送事件,在页面B接收事件,这个时
候有可能会发生接收不到的情况,为什么?因为生命周期的问题,按照Vue的生命周期,销毁事件是在当前组件完
全判定为未引用时候才会收回,上面的情况下,B页面组件的创建是在A页面组件销毁之前的,所以需要注意,而且
不要重名
如果有使用过react的同学可能会说,我们react用redux,说白了,其实就是状态机,无论是Vuex还是Redux其
实本质上都是一样的,就是状态管理,最早出现的是Flux,后边围绕着Flux出现了很多的前端状态管理架构思想,
专门解决软件的结构问题,中小型项目不建议使用,因为还要额外的安装包,引入一些列的概念,不要想的太神秘,
工具不就是拿来用的么,我感觉暂时用不到,用到的时候直接看API
学东西要知其然,知其所以然,我用过AngularJs/Angular,以此对比,便于理解
-它们都有双向绑定的概念,但是实现的方式是不同的,简要对比一下
-AngularJs其实就是Angular1,后来Angular2更名未Angular,AngularJs采用的是脏值检查,AngularJs在 scope 模型上设置了一个监听队
-列,用来监听数据变化并更新 view 。每次绑定一个东西到 view 上时 AngularJS 就会往 $watch 队列里插入一条 $watch,用来检测它监视的
-model 里是否有变化的东西。当浏览器接收到可以被 AngularJs context 处理的事件时,$digest 循环就会触发,遍历所有的 $watch,最后
-$apply应用到dom,从而更新视图
-Angular是AngularJs的升级版,Angular中引入了zoneJs,将JavaScript的异步任务都包裹了一层,这些异步任务都将运行在ZoneJs的
-content中,这也是为什么Angular选择了拥抱浏览器原生的对象和方法的原因,当ZoneJs钩子被调用的时候,通知Angular,Angular
-此时再做相应的脏值检查,更新DOM即可
-vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时
-发布消息给订阅者,触发相应的监听回调
-
- 先了解一个这样的问题,Javascript在整个运行时都可以被重写
-Angular2启动的时候会对浏览器API打低级补丁,例如AddEventListener(),会覆盖原有的方法,对原有方法进行扩展
-这样才有机会进行更改检测,并做相关处理,对于浏览器的低级API补丁,Angular2采用Zonejs来完成,这是一种通用
-的机制,我们可以为浏览器添加额外的功能,Angular2内部使用Zone来触发更改机制,还有一种可能是执行应用程序
-分析,或跟踪多个虚拟机的堆栈信息进行跟踪
- ZoneJS对浏览器所有基础事件进行了补丁,timeOut,interval,Ajax,click,hover等等,但是它是有限制的,因为zonejs不
-支持异步浏览器API,例如indexDB的回调,这样就解释了为什么他的变化会被检测到
-Angular2启动的时候,每一个组件都有一个关联的更改检测器
-1.缺省的变更机制
- 对于模板中使用的表达式,现有值与原来的值进行比较,默认情况的检查不会做深度对比,仅仅会对使用的属性进行对比
-2.changeDetection.OnPush && Immutable.js类似库
- 此种情况下引用的变更才会触发,而属性的改变不会触发,这样的检查显然是不靠谱的,所以引入了Immutable.js,来确保
-对象的不可变性,同时Angular2采用的是单向的数据流,这样就避免了angular1的双向绑定那个三重的for循环,进而提升了
-性能,Angular2的dev和生产模式下也是不同的,对于检查,在生产环境只会检查一次
-1 | constructor(private ref:ChangeDetectorRef){ |
Angular2和angular1的默认检查还是有很大不同的,做了一些优化,而且在Angular2中,变化检测是可以选择的
-
- HTML5新推出的Dialog,感觉就和之前废弃的marquee差不多,下面就是它的一个基本例子
-<dialog>
- <div style="width:300px;height:200px;">我是新版的Dialog</div>
- </dialog>
-let MyDialog = document.getElementsByTagName('dialog')[0];
- MyDialog.showModal();//展示对话框
- MyDialog.close();//关闭对话框
- 其实还有很多,想详细了解,很简单,复制上边代码试一下就可以了
-作为一个DOM元素,基本的事件都可以应用在Modal身上
- let MyDialog = document.getElementsByTagName('dialog')[0];
- MyDialog.onclick = function(){ console.log('我被点击了')};
- MyDialog.onblur = function(){ console.log('我失去了焦点')};
- MyDialog.onclose = function(){ console.log('我被关闭了')};
-一如我们覆盖默认的滚动条样式一样,我们可以设置其伪元素来达到覆盖样式的目的
- dialog {
- width: 300px;
- height:200px
- }
- dialog::backdrop {
- background-color: #dddddd;
- }
-Chrhome已经支持了,其他浏览器,应该不久之后也会支持
-
-
- HTML5新推出的Dialog,感觉就和之前废弃的marquee差不多,下面就是它的一个基本例子
-<dialog>
- <div style="width:300px;height:200px;">我是新版的Dialog</div>
- </dialog>
-let MyDialog = document.getElementsByTagName('dialog')[0];
- MyDialog.showModal();//展示对话框
- MyDialog.close();//关闭对话框
- 其实还有很多,想详细了解,很简单,复制上边代码试一下就可以了
-作为一个DOM元素,基本的事件都可以应用在Modal身上
- let MyDialog = document.getElementsByTagName('dialog')[0];
- MyDialog.onclick = function(){ console.log('我被点击了')};
- MyDialog.onblur = function(){ console.log('我失去了焦点')};
- MyDialog.onclose = function(){ console.log('我被关闭了')};
-一如我们覆盖默认的滚动条样式一样,我们可以设置其伪元素来达到覆盖样式的目的
- dialog {
- width: 300px;
- height:200px
- }
- dialog::backdrop {
- background-color: #dddddd;
- }
-Chrhome已经支持了,其他浏览器,应该不久之后也会支持
-
-
- 新的打包工具,他的名字叫Parcel,让你眼前一亮的感觉,Parcel GitHub地址
-如果你有Node/Yarn都可以 ,安装还是很简单
-yarn global add parcel-bundler
- npm install -g parcel-bundler
-//打开命令行,新建文件,parcel index.html
-<html>
- <body>
- <script> console.log(1);</script>
- </body>
- </html>
- //打开你的浏览器 http://localhost:1234
-有没有惊爆你的眼球,这。。。居然可以这样运行,简直是匪夷所思啊!
-//打开命令行,新建文件,parcel index.html
-<html>
- <body>
- <script> console.log(1);</script>
- </body>
- </html>
- //打开你的浏览器 http://localhost:1234
-有没有惊爆你的眼球,这。。。居然可以这样运行,简直是匪夷所思啊
-Parcel是无需任何配置的,是基于资源的,这意味着你的入口文件不必像之前一样,你的入口文件可以是任
意形态的资源,Parcel会自动的分析这些文件和包的依赖关系,同类资源会被组合到统一bundle中,同时
Parcel支持CommonJS 和 ES6 两种模块语法,无论是required还是import
虽然Parcel零配置,但是你需要额外的工具库,那么请安装它,parcel会自动扫描package.json文件,之后就可
以直接在项目中使用,比如我想构建scss
// 一行搞定
-npm install node-sass --save
-
-