bt365体育投注.主頁欢迎您!!

    <acronym id="zvmrr"></acronym>
    <td id="zvmrr"></td>
  • <tr id="zvmrr"><label id="zvmrr"></label></tr>
  • <acronym id="zvmrr"></acronym>
  • 杨川宝

    杨川宝 查看完整档案

    上海编辑山东财经大学  |  计算机 编辑七牛云存储  |  前端工程师 编辑填写个人主网站
    编辑

    vue react angular 七牛云存储前端工程师

    个人动态

    杨川宝 关注了问题 · 2016-11-08

    解决请问我这是什么原因?【网络安全,nginx,php,js相关】

    已解决,更换了jquery导入为 七牛云静态资源加速。然后就不出现这个问题了。
    说明js文件内部有问题。也给自己提了个醒,不要乱使用外部js。谢谢回答的同学!

    clipboard.png

    偶尔刷新页面后,正常来说应该是都来自一个地址的。为什么会有三个从外面地址请求过来的东西?(上面画黑线的都是同一个地址,画黄色线的就是来自其他的地址)

    正常的应该是这样的:

    clipboard.png

    我是前端,我不是很懂这是为什么?(自己猜测是不是路由器或者服务器被劫持?)

    1.并没有使用cdn。

    2.js引用只有jquery 和 layui 2个。

    3.就是个登录页面, 并没有使用外部资源的js。

    4.这是页面头部:
    clipboard.png

    关注 8 回答 6

    杨川宝 关注了问题 · 2016-11-08

    解决请问我这是什么原因?【网络安全,nginx,php,js相关】

    已解决,更换了jquery导入为 七牛云静态资源加速。然后就不出现这个问题了。
    说明js文件内部有问题。也给自己提了个醒,不要乱使用外部js。谢谢回答的同学!

    clipboard.png

    偶尔刷新页面后,正常来说应该是都来自一个地址的。为什么会有三个从外面地址请求过来的东西?(上面画黑线的都是同一个地址,画黄色线的就是来自其他的地址)

    正常的应该是这样的:

    clipboard.png

    我是前端,我不是很懂这是为什么?(自己猜测是不是路由器或者服务器被劫持?)

    1.并没有使用cdn。

    2.js引用只有jquery 和 layui 2个。

    3.就是个登录页面, 并没有使用外部资源的js。

    4.这是页面头部:
    clipboard.png

    关注 8 回答 6

    杨川宝 发布了文章 · 2016-10-31

    vue2.0源码分析之理解响应式架构

    分享前啰嗦

    我之前介绍过vue1.0如何实现observerwatcher。本想继续写下去,可是vue2.0横空出世..所以
    直接看vue2.0吧。这篇文章在公司分享过,终于写出来了。我们采用用最精简的代码,还原vue2.0响应式架构实现
    以前写的那篇 vue 源码分析之如何实现 observer 和 watcher可以作为本次分享的参考。
    不过不看也没关系,但是最好了解下Object.defineProperty

    本文分享什么

    理解vue2.0的响应式架构,就是下面这张图
    vuedeptrace.jpg

    顺带介绍他比react快的其中一个原因

    本分实现什么

    const demo = new Vue({
      data: {
        text: "before",
      },
      //对应的template 为 <div><span>{{text}}</span></div>
      render(h){
        return h('div', {}, [
          h('span', {}, [this.__toString__(this.text)])
        ])
      }
    })
     setTimeout(function(){
       demo.text = "after"
     }, 3000)

    对应的虚拟dom会从
    <div><span>before</span></div> 变为 <div><span>after</span></div>
    好,开始吧!!!

    第一步, 讲data 下面所有属性变为observable

    来来来先看代码吧

        class Vue {
          constructor(options) {
            this.$options = options
            this._data = options.data
            observer(options.data, this._update)
            this._update()
          }
          _update(){
            this.$options.render()
          }
        }
    
    
        function observer(value, cb){
          Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))
        }
    
        function defineReactive(obj, key, val, cb) {
          Object.defineProperty(obj, key, {
            enumerable: true,
            configurable: true,
            get: ()=>{},
            set:newVal=> {
              cb()
            }
          })
        }
    
        var demo = new Vue({
          el: '#demo',
          data: {
            text: 123,
          },
          render(){
            console.log("我要render了")
          }
        })
    
         setTimeout(function(){
           demo._data.text = 444
         }, 3000)

    为了好演示我们只考虑最简单的情况,如果看了vue 源码分析之如何实现 observer 和 watcher可能就会很好理解,不过没关系,我们三言两语再说说,这段代码要实现的功能就是将

        var demo = new Vue({
          el: '#demo',
          data: {
            text: 123,
          },
          render(){
            console.log("我要render了")
          }
        })

    data 里面所有的属性置于 observer,然后data里面的属性,比如 text 以改变,就引起_update()函数调用进而重新渲染,是怎样做到的呢,我们知道其实就是赋值的时候就要改变对吧,当我给data下面的text 赋值的时候 set 函数就会触发,这个时候 调用 _update 就ok了,但是

         setTimeout(function(){
           demo._data.text = 444
         }, 3000)

    demo._data.text没有demo.text用着爽,没关系,我们加一个代理

          _proxy(key) {
            const self = this
            Object.defineProperty(self, key, {
              configurable: true,
              enumerable: true,
              get: function proxyGetter () {
                return self._data[key]
              },
              set: function proxySetter (val) {
                self._data[key] = val
              }
            })
          }

    然后在Vueconstructor加上下面这句

        Object.keys(options.data).forEach(key => this._proxy(key))

    第一步先说到这里,我们会发现一个问题,data中任何一个属性的值改变,都会引起
    _update的触发进而重新渲染,属性这显然不够精准啊

    第二步,详细阐述第一步为什么不够精准

    比如考虑下面代码

        new Vue({
          template: `
            <div>
              <section>
                <span>name:</span> {{name}}
              </section>
              <section>
                <span>age:</span> {{age}}
              </section>
            <div>`,
          data: {
            name: 'js',
            age: 24,
            height: 180
          }
        })
    
        setTimeout(function(){
          demo.height = 181
        }, 3000)

    template里面只用到了data上的两个属性nameage,但是当我改变height的时候,用第一步的代码,会不会触发重新渲染?会!,但其实不需要触发重新渲染,这就是问题所在!!

    第三步,上述问题怎么解决

    简单说说虚拟 DOM

    首先,template最后都是编译成render函数的(具体怎么做,就不展开说了,以后我会说的),然后render 函数执行完就会得到一个虚拟DOM,为了好理解我们写写最简单的虚拟DOM

        function VNode(tag, data, children, text) {
          return {
            tag: tag,
            data: data,
            children: children,
            text: text
          }
        }
    
        class Vue {
          constructor(options) {
            this.$options = options
            const vdom = this._update()
            console.log(vdom)
          }
          _update() {
            return this._render.call(this)
          }
          _render() {
            const vnode = this.$options.render.call(this)
            return vnode
          }
          __h__(tag, attr, children) {
            return VNode(tag, attr, children.map((child)=>{
              if(typeof child === 'string'){
                return VNode(undefined, undefined, undefined, child)
              }else{
                return child
              }
            }))
          }
          __toString__(val) {
            return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);
          }
        }
    
    
        var demo = new Vue({
          el: '#demo',
          data: {
            text: "before",
          },
          render(){
            return this.__h__('div', {}, [
              this.__h__('span', {}, [this.__toString__(this.text)])
            ])
          }
        })

    我们运行一下,他会输出

         {
           tag: 'div',
           data: {},
           children:[
             {
               tag: 'span',
               data: {},
               children: [
                 {
                   children: undefined,
                   data: undefined,
                   tag: undefined,
                   text: '' // 正常情况为 字符串 before,因为我们为了演示就不写代理的代码,所以这里为空
                 }
               ]
             }
           ]
         }

    这就是 虚拟最简单虚拟DOM,taghtml 标签名,data 是包含诸如 classstyle 这些标签上的属性,childen就是子节点,关于虚拟DOM就不展开说了。
    回到开始的问题,也就是说,我得知道,render 函数里面依赖了vue实例里面哪些变量(只考虑render 就可以,因为template 也会是帮你编译成render)。叙述有点拗口,还是看代码吧

        var demo = new Vue({
          el: '#demo',
          data: {
            text: "before",
            name: "123",
            age: 23
          },
          render(){
            return this.__h__('div', {}, [
              this.__h__('span', {}, [this.__toString__(this.text)])
            ])
          }
        })

    就像这段代码,render 函数里其实只依赖text,并没有依赖 nameage,所以,我们只要text改变的时候
    我们自动触发 render 函数 让它生成一个虚拟DOM就ok了(剩下的就是这个虚拟DOM和上个虚拟DOM做比对,然后操作真实DOM,只能以后再说了),那么我们正式考虑一下怎么做

    第三步,'touch' 拿到依赖

    回到最上面那张图,我们知道data上的属性设置defineReactive后,修改data 上的值会触发 set
    那么我们取data上值是会触发 get了。
    对,我们可以在上面做做手脚,我们先执行一下render,我们看看data上哪些属性触发了get,我们岂不是就可以知道 render 会依赖data 上哪些变量了。
    然后我么把这些变量做些手脚,每次这些变量变的时候,我们就触发render
    上面这些步骤简单用四个子概括就是 计算依赖。
    (其实不仅是render,任何一个变量的改别,是因为别的变量改变引起,都可以用上述方法,也就是computedwatch 的原理,也是mobx的核心)

    第一步,

    我们写一个依赖收集的类,每一个data 上的对象都有可能被render函数依赖,所以每个属性在defineReactive
    时候就初始化它,简单来说就是这个样子的

        class Dep {
          constructor() {
            this.subs = []
          }
          add(cb) {
            this.subs.push(cb)
          }
          notify() {
            console.log(this.subs);
            this.subs.forEach((cb) => cb())
          }
        }
        function defineReactive(obj, key, val, cb) {
          const dep = new Dep()
          Object.defineProperty(obj, key, {
            // 省略
          })
        }

    然后,当执行render 函数去'touch'依赖的时候,依赖到的变量get就会被执行,然后我们就可以把这个 render 函数加到 subs 里面去了。
    当我们,set 的时候 我们就执行 notify 将所有的subs数组里的函数执行,其中就包含render 的执行。
    至此就完成了整个图,好我们将所有的代码展示出来

        function VNode(tag, data, children, text) {
          return {
            tag: tag,
            data: data,
            children: children,
            text: text
          }
        }
    
        class Vue {
          constructor(options) {
            this.$options = options
            this._data = options.data
            Object.keys(options.data).forEach(key => this._proxy(key))
            observer(options.data)
            const vdom = watch(this, this._render.bind(this), this._update.bind(this))
            console.log(vdom)
          }
          _proxy(key) {
            const self = this
            Object.defineProperty(self, key, {
              configurable: true,
              enumerable: true,
              get: function proxyGetter () {
                return self._data[key]
              },
              set: function proxySetter (val) {
                self._data.text = val
              }
            })
          }
          _update() {
            console.log("我需要更新");
            const vdom = this._render.call(this)
            console.log(vdom);
          }
          _render() {
            return this.$options.render.call(this)
          }
          __h__(tag, attr, children) {
            return VNode(tag, attr, children.map((child)=>{
              if(typeof child === 'string'){
                return VNode(undefined, undefined, undefined, child)
              }else{
                return child
              }
            }))
          }
          __toString__(val) {
            return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);
          }
        }
    
        function observer(value, cb){
          Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))
        }
    
        function defineReactive(obj, key, val, cb) {
          const dep = new Dep()
          Object.defineProperty(obj, key, {
            enumerable: true,
            configurable: true,
            get: ()=>{
              if(Dep.target){
                dep.add(Dep.target)
              }
              return val
            },
            set: newVal => {
              if(newVal === val)
                return
              val = newVal
              dep.notify()
            }
          })
        }
        function watch(vm, exp, cb){
          Dep.target = cb
          return exp()
        }
    
        class Dep {
          constructor() {
            this.subs = []
          }
          add(cb) {
            this.subs.push(cb)
          }
          notify() {
            this.subs.forEach((cb) => cb())
          }
        }
        Dep.target = null
    
    
        var demo = new Vue({
          el: '#demo',
          data: {
            text: "before",
          },
          render(){
            return this.__h__('div', {}, [
              this.__h__('span', {}, [this.__toString__(this.text)])
            ])
          }
        })
    
    
         setTimeout(function(){
           demo.text = "after"
         }, 3000)

    我们看一下运行结果
    D4A9A9B8-03CA-4A73-A12F-30409E08D99D.png

    好我们解释一下 Dep.target 因为我们得区分是,普通的get,还是在查找依赖的时候的get
    所有我们在查找依赖时候,我们将

        function watch(vm, exp, cb){
          Dep.target = cb
          return exp()
        }

    Dep.target 赋值,相当于 flag 一下,然后 get 的时候

           get: () => {
              if (Dep.target) {
                dep.add(Dep.target)
              }
              return val
            },

    判断一下,就好了。
    到现在为止,我们再看那张图是不是就清楚很多了?

    总结

    我非常喜欢,vue2.0 以上代码为了好展示,都采用最简单的方式呈现。
    不过整个代码执行过程,甚至是命名方式都和vue2.0一样
    对比react,vue2.0 自动帮你监测依赖,自动帮你重新渲染,而
    react 要实现性能最大化,要做大量工作,比如我以前分享的
    react如何性能达到最大化(前传),暨react为啥非得使用immutable.js
    react 实现pure render的时候,bind(this)隐患
    而 vue2.0 天然帮你做到了最优,而且对于像万年不变的 如标签上静态的class属性,
    vue2.0 在重新渲染后做diff 的时候是不比较的,vue2.0比 达到性能最大化的react 还要快的一个原因
    然后源码在此,喜欢的记得给个 star 哦?
    后续,我会简单聊聊,vue2.0的diff。
    如果有疑问,可以在评论区留言哈

    查看原文

    赞 36 收藏 157 评论 26

    杨川宝 回答了问题 · 2016-05-23

    解决React使触摸事件生效,报错!!!

    你react 版本号是?

    关注 3 回答 2

    杨川宝 回答了问题 · 2016-03-16

    React Router 设置路由报错 "unexpected token <"

    这是 语法错误 。<Route path=":name" component={Instrument} />//这里name参数出入名字。应该是你注释包的错。。注释不能这样写

    关注 3 回答 2

    杨川宝 回答了问题 · 2016-03-06

    在 Redux 中进行 初始化/一次性 的操作科学的姿势是?

    没太明白你的意思…初始状态直接写在reducer中的state中就好了…

    关注 3 回答 1

    杨川宝 回答了问题 · 2016-01-26

    解决Redux如何结合React-Router?

    关注 8 回答 4

    杨川宝 赞了回答 · 2016-01-21

    解决有没有可能出现一个不同的字符串MD5出来相同的md5值呢?

    应该会~

    关注 10 回答 7

    杨川宝 发布了文章 · 2016-01-21

    解析神奇的 Object.defineProperty

    这个方法了不起啊。。vue.js是通过它实现双向绑定的。。而且Object.observe也被草案发起人撤回了。。所以defineProperty更有必要了解一下了。

    几行代码看他怎么用

    var a= {}
    Object.defineProperty(a,"b",{
      value:123
    })
    console.log(a.b);//123

    很简单,它接受三个参数,而且都是必填的。。

    传入参数

    • 第一个参数:目标对象

    • 第二个参数:需要定义的属性或方法的名字。

    • 第三个参数:目标属性所拥有的特性。(descriptor)

    前两个参数不多说了,一看代码就懂,主要看第三个参数descriptor,看看有哪些取值

    descriptor

    他又以下取值,我们简单认识一下,后面例子,挨个介绍。

    • value:属性的值(不用多说了)

    • writable:如果为false,属性的值就不能被重写,只能为只读了

    • configurable:总开关,一旦为false,就不能再设置他的(value,writable,configurable)

    • enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。

    • get:一会细说

    • set:一会细说

    descriptor 默认值

    我们再看看第一个例子

    var a= {}
    Object.defineProperty(a,"b",{
      value:123
    })
    console.log(a.b);//123

    我们只设置了 value,别的并没有设置,但是第一次的时候 可以简单的理解为(暂时这样理解)它会默认帮我们把writable,configurable,enumerable。都设上值,而且值还都是false。。也就是说,上面代码和下面是等价的的(仅限于第一次设置的时候)。

    var a= {}
    Object.defineProperty(a,"b",{
      value:123,
      writable:false,
      enumerable:false,
      configurable:false
    })
    console.log(a.b);//123

    以上非常重要哦。。并且以上理解对set 和 get 不起作用哦

    configurable

    总开关,第一次设置 false 之后,,第二次什么设置也不行了,比如说

    var a= {}
    Object.defineProperty(a,"b",{
      configurable:false
    })
    Object.defineProperty(a,"b",{
      configurable:true
    })
    //error: Uncaught TypeError: Cannot redefine property: b

    就会报错了。。

    注意上面讲的默认值。。。如果第一次不设置它会怎样。。会帮你设置为false。。所以。。第二次。再设置他会怎样?。。对喽,,会报错

    writable

    如果设置为fasle,就变成只读了。。

    var a = {}; 
    
    Object.defineProperty(o, "b", { 
        value : 123,
        writable : false });
    
    console.log(a.b); // 打印 37
    a.b = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
    console.log(o.a); // 打印 37, 赋值不起作用。

    enumerable

    属性特性 enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。

    var a= {}
    Object.defineProperty(a,"b",{
      value:3445,
      enumerable:true
    })
    console.log(Object.keys(a));// 打印["b"]

    改为false

    var a= {}
    Object.defineProperty(a,"b",{
      value:3445,
      enumerable:false //注意咯这里改了
    })
    console.log(Object.keys(a));// 打印[]

    for...in 类似,不赘述了

    set 和 get

    在 descriptor 中不能同时设置访问器(get 和 set)和 wriable 或 value,否则会错,就是说想用 get 和 set,就不能用 writable 或 value 中的任何一个。

    set 和 get,他俩干啥用的的。

    var a= {}
    Object.definePrope`请输入代码`rty(a,"b",{
      set:function(newValue){
        console.log("你要赋值给我,我的新值是"+newValue)
        },
      get:function(){
        console.log("你取我的值")
        return 2 //注意这里,我硬编码返回2
       }
    })
    a.b =1 //打印 你要赋值给我,我的新值是1
    console.log(a.b)    //打印 你取我的值
                        //打印 2    注意这里,和我的硬编码相同的

    简单来说,这个 “b” 赋值或者取值的时候会分别触发 set 和 get 对应的函数。

    这就是实现 observe的关键啊。

    下一篇,我会分析vue的observe的实现源码,聊聊自己如何一步一步实现$watch。

    查看原文

    赞 31 收藏 184 评论 21

    杨川宝 回答了问题 · 2016-01-19

    有没有用angularjs 做的网站啊?

    饿了么 阿里云

    关注 19 回答 10

    认证与成就

    • 获得 223 次点赞
    • 获得 7 枚徽章 获得 0 枚金徽章, 获得 2 枚银徽章, 获得 5 枚铜徽章

    擅长技能
    编辑

    开源项目 & 著作
    编辑

    (??? )
    暂时没有

    注册于 2015-08-22
    个人主页被 5.5k 人浏览

    bt365体育投注