精华内容
下载资源
问答
  • 解除设备PLC程序时间破解

    千次阅读 2020-07-13 20:36:40
    在出现 CORS 之前,我们都是使用 JSONP 的方式实现跨域,但是这种方式仅限于 GET 请求,而 CORS 的出现,为我们很好的解决了这个问题,这也是它成为一个趋势的原因 CORS 是一个W3C标准,全称是 跨域资源共享(Cross-...

    在出现 CORS 之前,我们都是使用 JSONP 的方式实现跨域,但是这种方式仅限于 GET 请求,而 CORS 的出现,为我们很好的解决了这个问题,这也是它成为一个趋势的原因
    CORS 是一个W3C标准,全称是 跨域资源共享(Cross-origin resource sharing)
    它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制
    CORS 需要浏览器和服务器同时支持,目前基本所有浏览器都支持该功能,IE浏览器不低于 IE10 即可
    整个 CORS 通信过程,都是浏览器自动完成,是不需要用户参与的,对于我们开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有的时候还会多出一次附加的请求,但这个过程中用户是无感的
    因此,实现 CORS 通信的关键是服务器,只要服务器设置了允许的 CORS 接口,就可以进行跨源通信,要了解怎么实现 CORS 跨域通信,我们还要先了解浏览器对每个请求都做了什么
    浏览器会将 CORS 请求分成两类,简单请求(simple request)和非简单请求(not-so-simple request),浏览器对这两种请求的处理,是不一样的
    简单请求
    什么是简单请求,其实很好理解记住两条就好了

    请求方法是 HEAD、GET、POST 三种方法之一
    HTTP的头信息不超出以下几种字段

    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)

    只要同时满足这两个条件,那么这个请求就是一个简单请求
    对于简单请求来说,浏览器会直接发出CORS请求,就是在这个请求的头信息中,自动添加一个 Origin 字段来说明本次请求的来源(协议 + 域名 + 端口),而后服务器会根据这个值,决定是否同意这次请求
    非简单请求
    知道了简单请求的定义,非简单请求就比较简单了,因为只要不是简单请求,它就是非简单请求
    浏览器应对非简单请求,会在正式通信之前,做一次查询请求,叫预检请求(preflight),也叫 OPTIONS 请求,因为它使用的请求方式是 OPTIONS ,这个请求是用来询问的
    浏览器会先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段,只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就会报跨域错误
    在这个预检请求里,头信息除了有表明来源的 Origin 字段外,还会有一个 Access-Control-Request-Method 字段和 Access-Control-Request-Headers 字段,它们分别表明了该浏览器 CORS 请求用到的 HTTP 请求方法和指定浏览器 CORS 请求会额外发送的头信息字段,如果你看的云里雾里,不要着急,我们看个例子
    如下为一个 AJAX 请求示例
    let url = ‘http://www.hahaha.com/abc’
    let xhr = new XMLHttpRequest()
    xhr.open(‘POST’, url, true)
    xhr.setRequestHeader(‘X-Token’, ‘YGJHJHGJAHSGJDHGSJGJHDGSJHS’)
    xhr.setRequestHeader(‘X-Test’, ‘YGJHJHGJAHSGJDHGSJGJHDGSJHS’)
    xhr.send()
    复制代码这个例子中,我们发送了一个POST请求,并在它的请求头中添加了一个自定义的 X-Token 和 X-Test 字段,因为添加了自定义请求头字段,所以它是一个非简单请求
    那么这个非简单请求在预检请求头信息中就会携带以下信息
    // 来源
    Origin: http://www.hahaha.com
    // 该CORS请求的请求方法
    Access-Control-Request-Method: POST
    // 额外发出的头信息字段
    Access-Control-Request-Headers: X-Token, X-Test
    复制代码withCredentials属性
    CORS 请求默认不发送 Cookie 和 HTTP 认证信息
    如果要把 Cookie 发到服务端,首先要服务端同意,指定Access-Control-Allow-Credentials 字段
    Access-Control-Allow-Credentials: true
    复制代码其次,客户端必须在发起的请求中打开 withCredentials 属性
    xhr = new XMLHttpRequest()
    xhr.withCredentials = true
    复制代码不然的话,服务端和客户端有一个没设置,就不会发送或处理Cookie
    虽说浏览器默认不发送 Cookie 和 HTTP 认证信息,但是有的浏览器,还是会一起发送Cookie,这时你也可以显式关闭 withCredentials
    xhr.withCredentials = false
    复制代码注意,如要发送 Cookie,Access-Control-Allow-Origin 字段就不能设为星号,必须指定明确的、与请求网页一致的域名,同时,Cookie 依然遵循同源政策,只有用服务器域名设置的 Cookie 才会上传,其他域名的 Cookie 并不会上传,且(跨源)原网页代码中的 document.cookie 也无法读取服务器域名下的 Cookie ,下面还会提到
    服务端CORS跨域配置
    上面的东西只是为了让我们理解CORS,但是要解决它还是需要服务端配置的,不同语言的配置项语法上可能有差异,但是内容肯定都是一样的
    配置允许跨域的来源
    Access-Control-Allow-Origin: *
    复制代码CORS 跨域请求中,最关键的就是 Access-Control-Allow-Origin 字段,是必需项,它表示服务端允许跨域访问的地址来源,你可以写入需要跨域的域名,也可以设为星号,表示同意任意跨源请求
    注意,将此字段设置为 * 是很不安全的,建议指定来源,并且设置为 * 号后,游览器将不会发送 Cookie,即使你的 XHR 设置了 withCredentials,也不会发送 Cookie
    配置允许跨域请求的方法
    Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT…
    复制代码该字段也是必需项,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法
    配置允许的请求头字段
    Access-Control-Allow-Headers: x-requested-with,content-type…
    复制代码如果你的请求中有自定义的请求头字段,那么此项也是必须的,它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在预检中请求的字段
    配置是否允许发送Cookie
    Access-Control-Allow-Credentials: true
    复制代码该字段可选,它的值是一个布尔值,表示是否允许发送Cookie,默认情况下,Cookie不包括在CORS请求之中
    设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器
    该字段只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可
    配置本次预检请求的有效期
    Access-Control-Max-Age: 1728000
    复制代码该字段可选,用来指定本次预检请求的有效期,单位为秒,上面结果中,有效期是20天(1728000秒),即允许缓存该条回应20天,在此期间如果你再次发出了这个接口请求,就不用发预检请求了,节省服务端资源
    常见的跨域预检请求抛错
    对于我们开发时,在跨域中最容易碰钉子的地方就是预检请求,所以列举几个预检请求错误的原因,知道哪错了可以直接找后端同学理论,关于预检请求,最终目的只有一个,客户端发送预检,服务端允许并返回200即可
    OPTIONS 404
    No ‘Access-Control-Allow-Origin’ header is present on the requested resource
    且 The response had HTTP status code 404
    复制代码服务端没有设置允许 OPTIONS 请求,那么在发起该预检请求时响应状态码会是404,因为无法找到对应接口地址
    那么你可能需要找到后端,优雅的告诉他,请允许下 OPTIONS 请求
    OPTIONS 405
    No ‘Access-Control-Allow-Origin’ header is present on the requested resource
    且 The response had HTTP status code 405
    复制代码服务端已经允许了 OPTIONS 请求,但是一些配置文件中(如安全配置)阻止了 OPTIONS 请求
    那么你可能需要找到后端,优雅的告诉他,请关闭对应的安全配置
    OPTIONS 200
    No ‘Access-Control-Allow-Origin’ header is present on the requested resource
    且 OPTIONS 请求 status 为 200
    复制代码服务器端允许了 OPTIONS 请求,配置文件中也没有阻止,但是头部匹配时出现不匹配现象
    所谓头部匹配,就比如 Origin 头部检查不匹配,或者少了一些头部的支持(如 X-Requested-With 等),然后服务端就会将 Response 返回给前端,前端检测到这个后就触发 XHR.onerror ,从而导致报错
    那么你可能需要找到后端,优雅的告诉他,请增加对应的头部支持
    OPTIONS 500
    这个就更简单了,服务端针对 OPTIONS 请求的代码出了问题,或者没有响应
    那么你可能需要找到后端,将 Network 中的错误信息截一图发给他,优雅的告诉他,检测到预检请求时,请把它搞成200
    No.7 Nginx代理跨域
    iconfont跨域解决
    浏览器跨域访问 js/css/img 等常规静态资源时被同源策略许可的,但 iconfont 字体文件比如 eot|otf|ttf|woff|svg 例外,此时可在 Nginx 的静态资源服务器中加入以下配置来解决
    location / {
    add_header Access-Control-Allow-Origin *;
    }
    复制代码反向代理接口跨域
    我们知道同源策略只是 浏览器 的安全策略,不是 HTTP 协议的一部分, 服务器端调用 HTTP 接口只是使用 HTTP 协议,不会执行 JS 脚本,不需要同源策略,也就不存在跨越问题
    通俗点说就是客户端浏览器发起一个请求会存在跨域问题,但是服务端向另一个服务端发起请求并无跨域,因为跨域问题归根结底源于同源策略,而同源策略只存在于浏览器
    那么我们是不是可以通过 Nginx 配置一个代理服务器,反向代理访问跨域的接口,并且我们还可以修改 Cookie 中 domain 信息,方便当前域 Cookie 写入
    Nginx 其实就是各种配置,简单易学,就算没接触过,也很好理解,我们来看示例
    首先假如我们的页面 a 在 http://www.hahaha.com 域下,但是我们的接口却在 http://www.hahaha1.com:9999 域下
    接着我们在页面 a 发起一个 AJAX 请求时,就会跨域,那么我们就可以通过 Nginx 配置一个代理服务器,域名和页面 a 相同,都是 http://www.hahaha.com ,用它来充当一个跳板的角色,反向代理访问 http://www.hahaha1.com 接口

    Nginx代理服务器

    server {
    listen 80;
    server_name www.hahaha.com;

    location / {
    # 反向代理地址
    proxy_pass http://www.hahaha1.com:9999;
    # 修改Cookie中域名
    proxy_cookie_domain www.hahaha1.com www.hahaha.com;
    index index.html index.htm;

    # 前端跨域携带了Cookie,所以Allow-Origin配置不可为*
    add_header Access-Control-Allow-Origin http://www.hahaha.com;  
    add_header Access-Control-Allow-Credentials true;
    

    }
    }
    复制代码没错,这个代理配置相信没接触过 Nginx 也能看明白,大部分都是我们上文提到过的,是不是很简单呢
    No.8 Node代理跨域
    Node 实现跨域代理,与 Nginx 道理相同,都是启一个代理服务器,就像我们常用的 Vue-CLI 配置跨域,其实也是 Node 启了一个代理服务,接下来我们来看看是如何做的
    Vue-CLI中代理的多种配置
    Vue-CLI 是基于 webpack 的,通过 webpack-dev-server 在本地启动脚手架,也就是在本地启动了一个 Node 服务,来实时监听和打包编译静态资源,由于都是封装好的,只需要配置即可,我们在 vue.config.js 中配置代理如下,写法很多,列几个常见的自行选择
    使用一
    module.exports = {
    //…
    devServer: {
    proxy: {
    ‘/api’: ‘http://www.hahaha.com’
    }
    }
    }
    复制代码如上所示时,当你请求 /api/abc 接口时就会被代理到 http://www.hahaha.com/api/abc
    使用二
    当然,你可能想将多个路径代理到同一个 target 下,那你可以使用下面这种方式
    module.exports = {
    //…
    devServer: {
    proxy: [{
    context: [’/api1’, ‘/api2’, ‘/api3’],
    target: ‘http://www.hahaha.com’,
    }]
    }
    }
    复制代码使用三
    正如我们第一种使用方式代理时,代理了 /api ,最终的代理结果是 http://www.hahaha.com/api/abc ,但是有时我们并不想代理时传递 /api,那么就可以使用下面这种方式,通过 pathRewrite 属性来进行路径重写
    module.exports = {
    //…
    devServer: {
    proxy: {
    ‘/api’: {
    target: ‘http://www.hahaha.com’,
    pathRewrite: {’^/api’ : ‘’}
    }
    }
    }
    }
    复制代码这个时候,/api/abc 接口就会被代理到 http://www.hahaha.com/abc
    使用四
    默认情况下,我们代理是不接受运行在 HTTPS 上,且使用了无效证书的后端服务器的
    如果你想要接受,需要设置 secure: false ,如下
    module.exports = {
    //…
    devServer: {
    proxy: {
    ‘/api’: {
    target: ‘https://www.hahaha.com’,
    secure: false
    }
    }
    }
    }
    复制代码使用五
    配置一个字段 changeOrigin ,当它为 true 时,本地就会虚拟一个服务器接收你的请求并且代你发送该请求,所以如果你要代理跨域,这个字段是必选项
    module.exports = {
    // …
    devServer: {
    proxy: {
    “/api”: {
    target: ‘http://www.hahaha.com’,
    changeOrigin: true,
    }
    }
    }
    }
    复制代码使用六
    如果你想配置多个不同的代理,也简单,如下所示,可以在任意代理中设置对应的代理规则
    module.exports = {
    // …
    devServer: {
    proxy: {
    “/api1”: {
    target: ‘http://www.hahaha1.com’,
    changeOrigin: true
    },
    “/api2”: {
    target: ‘http://www.hahaha2.com’,
    pathRewrite: {’^/api2’ : ‘’}
    },
    “/api3”: {
    target: ‘http://www.hahaha3.com’,
    changeOrigin: true,
    pathRewrite: {’^/api3’ : ‘’}
    }
    // …
    }
    }
    }
    复制代码注意,在本地配置代理跨域,只是解决开发时的跨域问题,当你的项目上线时,前端静态文件和后端在一个域下没有问题,如果并不在一个域下,依然会报跨域错误,这个时候还得需要后端配置跨域
    Node实现代理服务器
    这里我们使用 express + http-proxy-middleware 来搭建一个代理服务器,使用 http-proxy-middleware 这个中间件没有别的意思,只是因为 webpack-dev-server 里就是使用的它
    let express = require(‘express’)
    let proxy = require(‘http-proxy-middleware’)
    let app = express()

    app.use(’/’, proxy({
    // 代理跨域目标接口
    target: ‘http://www.hahaha1.com:9999’,
    changeOrigin: true,

    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) {
        res.header('Access-Control-Allow-Origin', 'http://www.hahaha.com')
        res.header('Access-Control-Allow-Credentials', 'true')
    },
    
    // 修改响应信息中的cookie域名,为false时,表示不修改
    cookieDomainRewrite: 'www.hahaha.com'
    

    }))

    app.listen(3000)
    复制代码No.9 WebSocket跨域
    WebSocket简介
    WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,2008年诞生,2011年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范,WebSocket API 也被 W3C 定为标准
    WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据, 在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,同时,它也是跨域的一种解决方案
    WebSocket特点

    建立在 TCP 协议之上,服务器端的实现比较容易

    与 HTTP 协议有着良好的兼容性,默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器

    数据格式比较轻量,性能开销小,通信高效

    可以发送文本,也可以发送二进制数据

    没有同源限制,客户端可以与任意服务器通信

    协议标识符是 ws(如果加密,则为 wss ),服务器网址就是 URL

    如下
    ws://www.hahaha.com:80/abc/def
    复制代码示例
    每个服务端语言对 websocket 有相应的支持,写法不同罢了,这里我们使用 Node 做示例
    在客户端我们可以直接使用 HTML5 的 websocket API ,服务端也可以使用 nodejs-websocket 实现 websocket server ,但是不建议这样做,因为原生 WebSocket API 使用起有些复杂,在浏览器的兼容性上还不够理想,所以我们使用 Socket.io,它很好地封装了 webSocket 接口,提供了更简单、灵活的接口,也对不支持 webSocket 的浏览器提供了向下兼容,使用 Socket.io 库实现 websocket,在发送数据时可以直接发送可序列化的对象,也可以自定义消息,利用事件字符串来区分不同消息,整个开发过程会舒服很多
    想要了解更多看官网即可 Socket.io - 传送门 ,我们来看示例
    客户端:http://www.hahaha.com/a.html

    复制代码服务端:http://www.hahaha1.com:3000
    const app = require(‘express’).createServer()
    const io = require(‘socket.io’)(app)

    app.listen(3000)

    io.on(‘connection’, (socket) => {
    socket.emit(‘my event’, { hello: ‘world’ })

    socket.on(‘my other event’, (data) => {
    console.log(data) // { my: ‘data’ }
    })
    })
    复制代码如上所示,使用了 Socket.io 之后的 websocket 连接是不是超级简单呢,跟着文档自己动手试试吧
    最后
    欢迎大家关注公众号「不正经的前端」,时不时发一篇文章,也没有花里胡哨的推广和广告,希望可以让大家随意点开一篇文章,都可以看到满满的干货,也可以直接加机器人好友备注「前端 | 后端 | 全栈」自动通过,加交流群,闲聊、吐槽、解决问题、交朋友都可以,当然技术为主

    按照时间线贴下了总结的比较全的几个帖子,还有其他的琐碎的文章,比较多就不贴了,这些文章都写的差不多,可能之间有互相抄袭,有互相借鉴,这些都是避免不了的,此文写的时候也借鉴了这些文章,只不过我手敲了一遍例子,又用我自己的理解码下来了,为此花了1周的业余时间,内容上与下面作者写的有些许雷同,那实属无奈,可以说是知识点就那么多,大家的总结稍有不同的地方就剩表达的语法,我也难受,还特意找了工具鉴别了下相似度,以免被误会,毕竟我也特别反感搬运工,嗯,又是一个深夜,终于收工了,睡觉喽,哦对了,码字不易,望点赞,如有错误,望指出,谢谢支持

    展开全文
  • 响应式是Vue的最大特色之一。如果你不知道幕后情况,它也是最神秘的地方之一。例如,为什么它不能用于对象和数组,不能用于诸如 localStorage 之类的其他东西? 让我们回答这个问题,在解决这个问题时,让Vue响应式...

    响应式是Vue的最大特色之一。如果你不知道幕后情况,它也是最神秘的地方之一。例如,为什么它不能用于对象和数组,不能用于诸如 localStorage 之类的其他东西?
    让我们回答这个问题,在解决这个问题时,让Vue响应式与 localStorage 一起使用。
    如果运行以下代码,则会看到计数器显示为静态值,并且不会像我们期望的那样发生变化,这是因为setInterval在 localStorage 中更改了该值。
    new Vue({
    el: “#counter”,
    data: () => ({
    counter: localStorage.getItem(“counter”)
    }),
    computed: {
    even() {
    return this.counter % 2 == 0;
    }
    },
    template: `


    Counter: {{ counter }}

    Counter is {{ even ? ‘even’ : ‘odd’ }}

    ` }); 复制代码// some-other-file.js setInterval(() => { const counter = localStorage.getItem("counter"); localStorage.setItem("counter", +counter + 1); }, 1000); 复制代码尽管Vue实例中的 counter 属性是响应式的,但它不会因为我们更改了它在 localStorage 中的来源而更改。 有多种解决方案,最好的也许是使用Vuex,并保持存储值与 localStorage 同步。但如果我们需要像本例中那样简单的东西呢?我们要深入了解一下Vue的响应式系统是如何工作的。 Vue 中的响应式 当Vue初始化组件实例时,它将观察data选项。这意味着它将遍历数据中的所有属性,并使用 Object.defineProperty 将它们转换为getter/setter。通过为每个属性设置自定义设置器,Vue可以知道属性何时发生更改,并且可以通知需要对更改做出反应的依赖者。它如何知道哪些依赖者依赖于一个属性?通过接入getters,它可以在计算的属性、观察者函数或渲染函数访问数据属性时进行注册。 // core/instance/state.js function initData () { // ... observe(data) } 复制代码// core/observer/index.js export function observe (value) { // ... new Observer(value) // ... }

    export class Observer {
    // …
    constructor (value) {
    // …
    this.walk(value)
    }

    walk (obj) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
    defineReactive(obj, keys[i])
    }
    }
    }

    export function defineReactive (obj, key, …) {
    const dep = new Dep()
    // …
    Object.defineProperty(obj, key, {
    // …
    get() {
    // …
    dep.depend()
    // …
    },
    set(newVal) {
    // …
    dep.notify()
    }
    })
    }
    复制代码所以,为什么 localStorage 不响应?因为它不是具有属性的对象。
    但是等一下,我们也不能用数组定义getter和setter,但Vue中的数组仍然是反应式的。这是因为数组在Vue中是一种特殊情况。为了拥有响应式的数组,Vue在后台重写了数组方法,并与Vue的响应式系统进行了修补。
    我们可以对 localStorage 做类似的事情吗?
    覆盖localStorage函数
    首先尝试通过覆盖localStorage方法来修复最初的示例,以跟踪哪些组件实例请求了localStorage项目。
    // LocalStorage项目键与依赖它的Vue实例列表之间的映射。
    const storeItemSubscribers = {};

    const getItem = window.localStorage.getItem;
    localStorage.getItem = (key, target) => {
    console.info(“Getting”, key);

    // 收集依赖的Vue实例
    if (!storeItemSubscribers[key]) storeItemSubscribers[key] = [];
    if (target) storeItemSubscribers[key].push(target);

    // 调用原始函数
    return getItem.call(localStorage, key);
    };

    const setItem = window.localStorage.setItem;
    localStorage.setItem = (key, value) => {
    console.info(“Setting”, key, value);

    // 更新相关Vue实例中的值
    if (storeItemSubscribers[key]) {
    storeItemSubscribers[key].forEach((dep) => {
    if (dep.hasOwnProperty(key)) dep[key] = value;
    });
    }

    // 调用原始函数
    setItem.call(localStorage, key, value);
    };
    复制代码new Vue({
    el: “#counter”,
    data: function() {
    return {
    counter: localStorage.getItem(“counter”, this) // 我们现在需要传递“this”
    }
    },
    computed: {
    even() {
    return this.counter % 2 == 0;
    }
    },
    template: `


    Counter: {{ counter }}

    Counter is {{ even ? ‘even’ : ‘odd’ }}

    ` }); 复制代码setInterval(() => { const counter = localStorage.getItem("counter"); localStorage.setItem("counter", +counter + 1); }, 1000); 复制代码在这个例子中,我们重新定义了 getItem 和 setItem,以便收集和通知依赖 localStorage 项目的组件。在新的 getItem 中,我们注意到哪个组件请求了哪个项目,在 setItems 中,我们联系所有请求该项目的组件,并重写它们的数据属性。 为了使上面的代码工作,我们必须向 getItem 传递一个对组件实例的引用,这就改变了它的函数签名。我们也不能再使用箭头函数了,因为否则我们就不会有正确的 this 值。 如果我们想做得更好,就必须更深入地挖掘。例如,我们如何在不显式传递依赖者的情况下跟踪它们? Vue如何收集依赖关系 为了获得启发,我们可以回到Vue的响应式系统。我们之前曾看到,访问数据属性时,数据属性的 getter 将使调用者订阅该属性的进一步更改。但是它怎么知道是谁做的调用呢?当我们得到一个数据属性时,它的 getter 函数没有任何关于调用者是谁的输入。Getter函数没有输入,它怎么知道谁要注册为依赖者呢? 每个数据属性维护一个需要在Dep类中进行响应的依赖项列表。如果我们在此类中进行更深入的研究,可以看到只要在注册依赖项时就已经在静态目标变量中定义了依赖项。这个目标是由一个非常神秘的Watche类确定的。实际上,当数据属性更改时,将实际通知这些观察程序,并且它们将启动组件的重新渲染或计算属性的重新计算。 但是,他们又是谁? 当Vue使 data 选项可观察时,它还会为每个计算出的属性函数以及所有watch函数(不应与Watcher类混为一谈)以及每个组件实例的render函数创建watcher。观察者就像这些函数的伴侣。他们主要做两件事:

    当它们被创建时,它们会评估函数。这将触发依赖关系的集合。
    当他们被通知他们所依赖的一个值发生变化时,他们会重新运行他们的函数。这将最终重新计算一个计算出的属性或重新渲染整个组件。

    在观察者调用其负责的函数之前,有一个重要的步骤发生了:他们将自己设置为Dep类中静态变量的目标。这样可以确保在访问响应式数据属性时将它们注册为从属。
    追踪谁调用了localStorage
    我们无法完全做到这一点,因为我们无法使用Vue的内部机制。但是,我们可以使用Vue的想法,即观察者可以在调用其负责的函数之前,将目标设置为静态属性。我们能否在调用 localStorage 之前设置对组件实例的引用?
    如果我们假设在设置 data 选项时调用了 localStorage,则可以将其插入 beforeCreate 和 created 中。这两个挂钩在初始化data选项之前和之后都会被触发,因此我们可以设置一个目标变量,然后清除该变量,并引用当前组件实例(我们可以在生命周期挂钩中访问该实例)。然后,在我们的自定义获取器中,我们可以将该目标注册为依赖项。
    我们要做的最后一点是使这些生命周期挂钩成为我们所有组件的一部分,我们可以通过整个项目的全局混合来做到这一点。
    // LocalStorage项目键与依赖它的Vue实例列表之间的映射
    const storeItemSubscribers = {};

    // 当前正在初始化的Vue实例
    let target = undefined;

    const getItem = window.localStorage.getItem;
    localStorage.getItem = (key) => {
    console.info(“Getting”, key);

    // 收集依赖的Vue实例
    if (!storeItemSubscribers[key]) storeItemSubscribers[key] = [];
    if (target) storeItemSubscribers[key].push(target);

    // 调用原始函数
    return getItem.call(localStorage, key);
    };

    const setItem = window.localStorage.setItem;
    localStorage.setItem = (key, value) => {
    console.info(“Setting”, key, value);

    // 更新相关Vue实例中的值
    if (storeItemSubscribers[key]) {
    storeItemSubscribers[key].forEach((dep) => {
    if (dep.hasOwnProperty(key)) dep[key] = value;
    });
    }

    // 调用原始函数
    setItem.call(localStorage, key, value);
    };

    Vue.mixin({
    beforeCreate() {
    console.log(“beforeCreate”, this._uid);
    target = this;
    },
    created() {
    console.log(“created”, this._uid);
    target = undefined;
    }
    });
    复制代码现在,当我们运行第一个示例时,我们将获得一个计数器,该计数器每秒增加一个数字。
    new Vue({
    el: “#counter”,
    data: () => ({
    counter: localStorage.getItem(“counter”)
    }),
    computed: {
    even() {
    return this.counter % 2 == 0;
    }
    },
    template: `


    Counter: {{ counter }}

    Counter is {{ even ? ‘even’ : ‘odd’ }}

    ` }); 复制代码setInterval(() => { const counter = localStorage.getItem("counter"); localStorage.setItem("counter", +counter + 1); }, 1000); 复制代码我们的思想实验结束 当我们解决了最初的问题时,请记住这主要是一个思想实验。它缺少一些功能,例如处理已删除的项目和未安装的组件实例。它还具有一些限制,例如组件实例的属性名称需要与存储在 localStorage 中的项目相同的名称。就是说,主要目标是更好地了解Vue响应式在幕后的工作方式并充分利用这一点,因此,我希望你能从所有这些事情中受益。
    展开全文
  • 清除密码,小孩乱设置.或者是之前朋友及家人购机店长设置的原来的帐号无法正常输入正确密码和帐号的不开机.华为P40/P40pro huawei P40/P40pro进不了系统需要线刷来清除密码的可以用这篇经验来一步一步把手机弄好...

    华为华为P40/P40pro huawei P40/P40pro忘记了锁屏密码帐号密码激活手机跳过清除刷机不了.无法换掉密码来开机启动.清除密码锁,小孩乱设置.或者是之前朋友及家人购机店长设置的原来的帐号无法正常输入正确密码和帐号的不开机.华为P40/P40pro huawei P40/P40pro进不了系统需要线刷来清除密码的可以用这篇经验来一步一步把手机弄好新机如初一样,下面分享方法

    在这里插入图片描述
    一。官网找回,

    1。电脑或手机登录华为官网:www.huawei.com 然后点击右上角的登录

    在这里插入图片描述
    2。进界面后点击忘记密码
    在这里插入图片描述
    3.进入后会出现几个找回密码的方案,请根据你的条件进行选择

    在这里插入图片描述
    二。通过电脑刷机解决

    1。直接用这个华为通用的原方清除帐号密码平台工具包直接进行清除解锁即可

    打开下载连接:

    参考1:https://share.weiyun.com/56X4xRN

    参考2:https://pan.baidu.com/s/1bIVpCnCA6IQeH3B_HENsrw 提取码:2uvn

    在你的电脑上或者浏览器上去粘贴.电脑回车键确定打开这个连接里面有解锁用的平台驱动方法和教程这些的

    在这里插入图片描述
    2.操作完成,成功激活

    在这里插入图片描述

    展开全文
  • 清除密码,小孩乱设置.或者是之前朋友及家人购机店长设置的原来的帐号无法正常输入正确密码和帐号的不开机.华为mate30pro huawei mate30进不了系统需要线刷来清除密码的可以用这篇经验来一步一步把手机弄好新机如初...

    华为mate30pro huawei mate30忘记了锁屏密码帐号密码激活手机跳过清除刷机不了.无法换掉密码来开机启动.清除密码锁,小孩乱设置.或者是之前朋友及家人购机店长设置的原来的帐号无法正常输入正确密码和帐号的不开机.华为mate30pro huawei mate30进不了系统需要线刷来清除密码的可以用这篇经验来一步一步把手机弄好新机如初一样,下面分享方法

    在这里插入图片描述

    一。官网找回,

    1。电脑或手机登录华为官网:www.huawei.com 然后点击右上角的登录
    在这里插入图片描述

    2。进界面后点击忘记密码
    在这里插入图片描述

    3.进入后会出现几个找回密码的方案,请根据你的条件进行选择
    在这里插入图片描述

    二。通过电脑刷机解决

    1。直接用这个华为通用的原方清除帐号密码平台工具包直接进行清除解锁即可

    打开下载连接:

    参考1:https://share.weiyun.com/56X4xRN

    参考2:https://pan.baidu.com/s/1bIVpCnCA6IQeH3B_HENsrw 提取码:2uvn

    在你的电脑上或者浏览器上去粘贴.电脑回车键确定打开这个连接里面有解锁用的平台驱动方法和教程这些的
    在这里插入图片描述

    2.操作完成,成功激活

    手机成功激活

    展开全文
  • 清除密码,小孩乱设置.或者是之前朋友及家人购机店长设置的原来的帐号无法正常输入正确密码和帐号的不开机.华为mate30pro huawei mate30进不了系统需要线刷来清除密码的可以用这篇经验来一步一步把手机弄好新机如初...
  • 华为手机怎么强制解除账户要输入解屏密码激活,备被需要账号密码激活如何解决设备关联华为帐号并被锁定帐号密码激活设备没有密码华为P40/华为P40PRO刷机教程刷机方法刷机步骤怎么激活手机清除锁定解锁完成需要...
  • 华为手机怎么强制解除账户要输入解屏密码激活,备被需要账号密码激活如何解决设备关联华为帐号并被锁定帐号密码激活设备没有密码华为P50PRO/华为P50 5G手机刷机教程刷机方法刷机步骤怎么激活手机清除锁定解锁完成...
  • 华为手机怎么强制解除账户要输入解屏密码激活,备被需要账号密码激活如何解决设备关联华为帐号并被锁定帐号密码激活设备没有密码华为畅享20/畅享20PRO刷机教程刷机方法刷机步骤怎么激活手机清除锁定解锁完成需要...
  • 华为P10_P10PLUS解锁视频解锁方法华为VTR/VKY-AL00忘记账户密码怎么解锁设备激活手机ID强制解开屏幕账号设备已锁定关联手机成功解除清除锁定平台软件下载.zip
  • 华为荣耀平板电脑解锁视频方法强制清除开机BAH2-W09_AGS-AL00A怎么解锁账户密码激活手机平板电脑设备关联号解除方法成功解开屏幕开机办法.zip解压用即可
  • 行业分类-设备装置-一种航天器扩频应答机在轨闩故障的解除方法.zip
  • 华为手机怎么强制解除账户要输入解屏密码激活,备被需要账号密码激活如何解决设备关联华为帐号并被锁定帐号密码激活设备没有密码华为P30PRO/华为P20PRO刷机教程刷机方法刷机步骤怎么激活手机清除锁定解锁完成需要...
  • 荣耀9,荣耀9i青春版解锁视频激活手机账户强制解锁教程荣耀 LLD-AL20_AL00_LLD-AL30忘记账户密码怎么解锁设备激活手机ID强制解开屏幕账号设备已锁定关联手机成功解除软件平台软件下载.zip解压用有教程
  • 华为手机和荣耀手机怎么解锁设备锁激活锁获取解锁码(绕开激活手机华为通道,解锁帐户密码)教程开机密码忘记解锁方法教程设备关联华为帐号并被锁定帐号密码激活设备没有密码怎么激活手机清除锁定解锁完成在遇到一些...
  • iPhone/iPad绕过苹果官方服务器激活ID设备,近日看到很多媒体都报道了国外黑客绕过iCloud激活苹果设备的新闻。但是我看过以后感觉这位朋友可能只是从理论方面出发的,应该没有实际操作,如果讨论道德,那我们很...
  • 荣耀8X荣耀9X忘记密码怎么办怎么解锁8X9X机主已被锁定设备锁无法激活了解开账户ID锁不记得密码清除方法下好后解压用有 方法能成功搞好
  • 苹果激活怎么解除?苹果手机上的激活可以确保我们的设备和信息安全,在设备丢失或者被窃的时候,开启的激活可以帮助我们减少损失。很多人不太了解苹果手机的激活,今天就教大家关闭激活的方法。 情景一:...
  • HUAWEI华为mate20X 5G解锁教程视频强制清除账户ID密码方法MATE20PRO指纹屏幕锁设备锁忘记账号密码全不记得怎么办解锁教程方法.解锁平台驱动平台包下载流程
  • 那么该怎么解除电脑键盘呢?今天小编就教下大家解除电脑键盘的方法。情况一:小键盘锁定1、电脑键盘住了有两个可能,第一种是小键盘住了,第二种是所有键都住了。2、如果是小键盘住了,按一下小键盘上方...
  • 荣耀20s荣耀V20已锁定手机无法解锁激活怎么办荣耀20V20解开账户ID账号不记得密码清除方法流程刷机包下载线刷解锁平台下载使用方法
  • 申诉帐解锁方法绑定的号解锁华为帐号密码,关联了激活手机方法步骤HONOR V30/V30PRO+HONOR 30 PRO+设备关联了华为帐号密无法找回重置修改密码来进行登陆它激活不了设备及自己升级.更新ROOT后不开机.定屏重启...
  • 申诉帐解锁方法绑定的号解锁华为帐号密码,关联了激活手机方法步骤HUAWEI华为平板MATEPAD 5G版华为平台MatePad Pro设备关联了华为帐号密无法找回重置修改密码来进行登陆它激活不了设备及自己升级.更新ROOT后不开机....
  • 最近发现好多朋友手机在恢复出厂设置之后或者刷机之后,出现激活手机,此设备已绑定欢太帐号并被锁定,请输入该帐号的密码激活设备,但是有部分是购买的二手手机或者原来注册OPPO欢太帐号的手机卡号已经更换无法激活...
  • 申诉帐解锁方法绑定的号解锁华为帐号密码,关联了激活手机方法步骤华为荣耀30 Pro荣耀20Ppro/荣耀30/荣耀40 Pro设备关联了华为帐号密无法找回重置修改密码来进行登陆它激活不了设备及自己升级.更新ROOT后不开机.定...
  • 小米手机被设备锁定是无法强制解除的,需要按照小米官方要求进行申诉操作,解除方法如下: 1、首先打开小米官网并登录,接着点击人工客服。 2、然后选择小米手机,输入设备锁定并发送。 3、点击申诉解锁信息...
  • 账户密码输入错误失败激活荣耀手机被机主锁定了设备锁账户ID华为激活失败解锁教程视频如何申诉激活账号密码清除重新设定流程华为账号密码账户ID锁激活手机锁华为手机最新解锁视频方法.最新华为手机荣耀手机解锁平台...
  • 申诉帐解锁方法绑定的号解锁华为帐号密码,关联了激活手机方法步骤华为HONOR 20/30/honor V20/20i/30S设备关联了华为帐号密无法找回重置修改密码来进行登陆它激活不了设备及自己升级.更新ROOT后不开机.定屏重启...
  • USB设备类-屏幕.rar

    2010-04-15 16:16:56
    USB屏幕.exe--------文件... 再用 USB屏幕.exe 注册,拔掉USB设备就可以锁屏了,插入注册过的USB设备即可解除锁屏。 -----------------------------------------------------by:red.fox E-mail:black-fox@126.com
  • (1)查看哪个表被 select b.owner,b.object_name,a.session_id,a.locked_mode from vKaTeX parse error: Expected 'EOF', got '#' at position 115: …,b.sid,b.serial#̲,logon_time fro…locked_object a,v$...
  • 已关联设备号锁定输入才能激活.申诉激活失败.要怎么办呢遇到无法激活手机账号密码有账户在开机界面要激活的怎么办重置出厂不开机.定屏开机LOGO反复重启recovery恢复模式.HUAWEI MATE30/mate 30s/MATE30 Pro刷机包...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,789
精华内容 6,715
关键字:

如何解除设备锁