我跟随人们。我去看看他们的网站。许多人都有一个像这样的“跟随”按钮
但是,如果我,我已经关注此人,按钮应该像这样一直“变灰”
但是一旦你刷新页面或稍后返回它看起来我不是追随者。相反,你需要点击网站上的“关注”按钮,然后出现twitter的对话框,告诉我我已经'跟随'
当你将鼠标悬停在此按钮上时,它会以红色显示“取消关注”。
Twitter是否有某种Follower.Event.Subscribe
功能可以识别他们所关注网站的人员。如果他们能识别网站上的关注号码,那么为什么不记住粉丝呢?
答案 0 :(得分:1)
它降低了Cookie。如果令牌不在您的浏览器历史记录中,Twitter会如何知道您已点击它?
您可能会发现,如果您首先登录Twitter然后转到网站并点击刷新,则会更改为以下内容。
另外,如果你喜欢我的浏览器有一个微小的缓存,可以刷新或关闭所有东西,那么你肯定没有机会记住你,因为你立即杀死了cookie。
<强>更新强>
现在看来twitter已经改变了如何使用跟随按钮。
之前如果我登录了Twitter并且按下了它就会跟着它们,但现在我看到一个带有流等的网关弹出窗口。
似乎已经发生的事情是Twitter已停止cookie丢弃并选择了网关api。
对于按钮,键位于以下代码中:
! function() {
Function && Function.prototype && Function.prototype.bind && (/MSIE [678]/.test(navigator.userAgent) || ! function t(e, n, r) {
function i(s, a) {
if (!n[s]) {
if (!e[s]) {
var u = "function" == typeof require && require;
if (!a && u) return u(s, !0);
if (o) return o(s, !0);
var c = new Error("Cannot find module '" + s + "'");
throw c.code = "MODULE_NOT_FOUND", c
}
var f = n[s] = {
exports: {}
};
e[s][0].call(f.exports, function(t) {
var n = e[s][1][t];
return i(n ? n : t)
}, f, f.exports, t, e, n, r)
}
return n[s].exports
}
for (var o = "function" == typeof require && require, s = 0; s < r.length; s++) i(r[s]);
return i
}({
1: [
function(t, e, n) {
(function() {
"use strict";
function t(t) {
return "function" == typeof t || "object" == typeof t && null !== t
}
function n(t) {
return "function" == typeof t
}
function r(t) {
return "object" == typeof t && null !== t
}
function i() {}
function o() {
return function() {
process.nextTick(c)
}
}
function s() {
var t = 0,
e = new F(c),
n = document.createTextNode("");
return e.observe(n, {
characterData: !0
}),
function() {
n.data = t = ++t % 2
}
}
function a() {
var t = new MessageChannel;
return t.port1.onmessage = c,
function() {
t.port2.postMessage(0)
}
}
function u() {
return function() {
setTimeout(c, 1)
}
}
function c() {
for (var t = 0; U > t; t += 2) {
var e = q[t],
n = q[t + 1];
e(n), q[t] = void 0, q[t + 1] = void 0
}
U = 0
}
function f() {}
function l() {
return new TypeError("You cannot resolve a promise with itself")
}
function d() {
return new TypeError("A promises callback cannot return that same promise.")
}
function h(t) {
try {
return t.then
} catch (e) {
return J.error = e, J
}
}
function p(t, e, n, r) {
try {
t.call(e, n, r)
} catch (i) {
return i
}
}
function m(t, e, n) {
A(function(t) {
var r = !1,
i = p(n, e, function(n) {
r || (r = !0, e !== n ? w(t, n) : _(t, n))
}, function(e) {
r || (r = !0, b(t, e))
}, "Settle: " + (t._label || " unknown promise"));
!r && i && (r = !0, b(t, i))
}, t)
}
function g(t, e) {
e._state === B ? _(t, e._result) : t._state === z ? b(t, e._result) : E(e, void 0, function(e) {
w(t, e)
}, function(e) {
b(t, e)
})
}
function v(t, e) {
if (e.constructor === t.constructor) g(t, e);
else {
var r = h(e);
r === J ? b(t, J.error) : void 0 === r ? _(t, e) : n(r) ? m(t, e, r) : _(t, e)
}
}
function w(e, n) {
e === n ? b(e, l()) : t(n) ? v(e, n) : _(e, n)
}
function y(t) {
t._onerror && t._onerror(t._result), x(t)
}
function _(t, e) {
t._state === H && (t._result = e, t._state = B, 0 === t._subscribers.length || A(x, t))
}
function b(t, e) {
t._state === H && (t._state = z, t._result = e, A(y, t))
}
function E(t, e, n, r) {
var i = t._subscribers,
o = i.length;
t._onerror = null, i[o] = e, i[o + B] = n, i[o + z] = r, 0 === o && t._state && A(x, t)
}
function x(t) {
var e = t._subscribers,
n = t._state;
if (0 !== e.length) {
for (var r, i, o = t._result, s = 0; s < e.length; s += 3) r = e[s], i = e[s + n], r ? O(n, r, i, o) : i(o);
t._subscribers.length = 0
}
}
function T() {
this.error = null
}
function R(t, e) {
try {
return t(e)
} catch (n) {
return W.error = n, W
}
}
function O(t, e, r, i) {
var o, s, a, u, c = n(r);
if (c) {
if (o = R(r, i), o === W ? (u = !0, s = o.error, o = null) : a = !0, e === o) return void b(e, d())
} else o = i, a = !0;
e._state !== H || (c && a ? w(e, o) : u ? b(e, s) : t === B ? _(e, o) : t === z && b(e, o))
}
function N(t, e) {
try {
e(function(e) {
w(t, e)
}, function(e) {
b(t, e)
})
} catch (n) {
b(t, n)
}
}
function C(t, e, n, r) {
this._instanceConstructor = t, this.promise = new t(f, r), this._abortOnReject = n, this._validateInput(e) ? (this._input = e, this.length = e.length, this._remaining = e.length, this._init(), 0 === this.length ? _(this.promise, this._result) : (this.length = this.length || 0, this._enumerate(), 0 === this._remaining && _(this.promise, this._result))) : b(this.promise, this._validationError())
}
function I() {
throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")
}
function P() {
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")
}
function S(t) {
this._id = X++, this._state = void 0, this._result = void 0, this._subscribers = [], f !== t && (n(t) || I(), this instanceof S || P(), N(this, t))
}
var j;
j = Array.isArray ? Array.isArray : function(t) {
return "[object Array]" === Object.prototype.toString.call(t)
};
var L, k = j,
U = (Date.now || function() {
return (new Date).getTime()
}, Object.create || function(t) {
if (arguments.length > 1) throw new Error("Second argument not supported");
if ("object" != typeof t) throw new TypeError("Argument must be an object");
return i.prototype = t, new i
}, 0),
A = function(t, e) {
q[U] = t, q[U + 1] = e, U += 2, 2 === U && L()
},
M = "undefined" != typeof window ? window : {},
F = M.MutationObserver || M.WebKitMutationObserver,
D = "undefined" != typeof Uint8ClampedArray && "undefined" != typeof importScripts && "undefined" != typeof MessageChannel,
q = new Array(1e3);
L = "undefined" != typeof process && "[object process]" === {}.toString.call(process) ? o() : F ? s() : D ? a() : u();
var H = void 0,
B = 1,
z = 2,
J = new T,
W = new T;
C.prototype._validateInput = function(t) {
return k(t)
}, C.prototype._validationError = function() {
return new Error("Array Methods must be provided an Array")
}, C.prototype._init = function() {
this._result = new Array(this.length)
};
var K = C;
C.prototype._enumerate = function() {
for (var t = this.length, e = this.promise, n = this._input, r = 0; e._state === H && t > r; r++) this._eachEntry(n[r], r)
}, C.prototype._eachEntry = function(t, e) {
var n = this._instanceConstructor;
r(t) ? t.constructor === n && t._state !== H ? (t._onerror = null, this._settledAt(t._state, e, t._result)) : this._willSettleAt(n.resolve(t), e) : (this._remaining--, this._result[e] = this._makeResult(B, e, t))
}, C.prototype._settledAt = function(t, e, n) {
var r = this.promise;
r._state === H && (this._remaining--, this._abortOnReject && t === z ? b(r, n) : this._result[e] = this._makeResult(t, e, n)), 0 === this._remaining && _(r, this._result)
}, C.prototype._makeResult = function(t, e, n) {
return n
}, C.prototype._willSettleAt = function(t, e) {
var n = this;
E(t, void 0, function(t) {
n._settledAt(B, e, t)
}, function(t) {
n._settledAt(z, e, t)
})
};
var V = function(t, e) {
return new K(this, t, !0, e).promise
},
$ = function(t, e) {
function n(t) {
w(o, t)
}
function r(t) {
b(o, t)
}
var i = this,
o = new i(f, e);
if (!k(t)) return b(o, new TypeError("You must pass an array to race.")), o;
for (var s = t.length, a = 0; o._state === H && s > a; a++) E(i.resolve(t[a]), void 0, n, r);
return o
},
Y = function(t, e) {
var n = this;
if (t && "object" == typeof t && t.constructor === n) return t;
var r = new n(f, e);
return w(r, t), r
},
G = function(t, e) {
var n = this,
r = new n(f, e);
return b(r, t), r
},
X = 0,
Q = S;
S.all = V, S.race = $, S.resolve = Y, S.reject = G, S.prototype = {
constructor: S,
then: function(t, e) {
var n = this,
r = n._state;
if (r === B && !t || r === z && !e) return this;
var i = new this.constructor(f),
o = n._result;
if (r) {
var s = arguments[r - 1];
A(function() {
O(r, i, s, o)
})
} else E(n, i, t, e);
return i
},
"catch": function(t) {
return this.then(null, t)
}
};
var Z = function() {
var t;
t = "undefined" != typeof global ? global : "undefined" != typeof window && window.document ? window : self;
var e = "Promise" in t && "resolve" in t.Promise && "reject" in t.Promise && "all" in t.Promise && "race" in t.Promise && function() {
var e;
return new t.Promise(function(t) {
e = t
}), n(e)
}();
e || (t.Promise = Q)
},
tt = {
Promise: Q,
polyfill: Z
};
"function" == typeof define && define.amd ? define(function() {
return tt
}) : "undefined" != typeof e && e.exports ? e.exports = tt : "undefined" != typeof this && (this.ES6Promise = tt)
}).call(this)
}, {}
],
2: [
function(t, e, n) {
var r = t(3),
i = t(36);
e.exports = function(t, e, n) {
var o, s, a, u, c = i.aug({}, n);
return arguments.length > 1 && "[object Object]" !== String(e) ? ((null === e || void 0 === e) && (c.expires = -1), "number" == typeof c.expires && (o = c.expires, s = new Date((new Date).getTime() + 60 * o * 1e3), c.expires = s), e = String(e), r.cookie = [encodeURIComponent(t), "=", c.raw ? e : encodeURIComponent(e), c.expires ? "; expires=" + c.expires.toUTCString() : "", c.path ? "; path=" + c.path : "", c.domain ? "; domain=" + c.domain : "", c.secure ? "; secure" : ""].join("")) : (c = e || {}, u = c.raw ? function(t) {
return t
} : decodeURIComponent, (a = new RegExp("(?:^|; )" + encodeURIComponent(t) + "=([^;]*)").exec(r.cookie)) ? u(a[1]) : null)
}
}, {
3: 3,
36: 36
}
],
3: [
function(t, e, n) {
e.exports = document
}, {}
],
4: [
function(t, e, n) {
e.exports = location
}, {}
],
5: [
function(t, e, n) {
e.exports = navigator
}, {}
],
6: [
function(t, e, n) {
e.exports = window
}, {}
],
7: [
function(t, e, n) {
function r(t) {
return a.isType("string", t) ? t.split(".") : a.isType("array", t) ? t : []
}
function i(t, e) {
var n = r(e),
i = n.slice(0, -1);
return i.reduce(function(t, e, n) {
if (t[e] = t[e] || {}, !a.isObject(t[e])) throw new Error(i.slice(0, n + 1).join(".") + " is already defined with a value.");
return t[e]
}, t)
}
function o(t, e) {
e = e || s, e[t] = e[t] || {}, Object.defineProperty(this, "base", {
value: e[t]
}), Object.defineProperty(this, "name", {
value: t
})
}
var s = t(6),
a = t(36);
a.aug(o.prototype, {
get: function(t) {
var e = r(t);
return e.reduce(function(t, e) {
return a.isObject(t) ? t[e] : void 0
}, this.base)
},
set: function(t, e, n) {
var o = r(t),
s = i(this.base, t),
a = o.slice(-1);
return n && a in s ? s[a] : s[a] = e
},
init: function(t, e) {
return this.set(t, e, !0)
},
unset: function(t) {
var e = r(t),
n = this.get(e.slice(0, -1));
n && delete n[e.slice(-1)]
},
aug: function(t) {
var e = this.get(t),
n = a.toRealArray(arguments).slice(1);
if (e = "undefined" != typeof e ? e : {}, n.unshift(e), !n.every(a.isObject)) throw new Error("Cannot augment non-object.");
return this.set(t, a.aug.apply(null, n))
},
call: function(t) {
var e = this.get(t),
n = a.toRealArray(arguments).slice(1);
if (!a.isType("function", e)) throw new Error("Function " + t + "does not exist.");
return e.apply(null, n)
},
fullPath: function(t) {
var e = r(t);
return e.unshift(this.name), e.join(".")
}
}), e.exports = o
}, {
36: 36,
6: 6
}
],
8: [
function(t, e, n) {
function r(t) {
var e, n, r, i = 0;
for (o = {}, t = t || s, e = t.getElementsByTagName("meta"); n = e[i]; i++) /^twitter:/.test(n.name) && (r = n.name.replace(/^twitter:/, ""), o[r] = n.content)
}
function i(t) {
return o[t]
}
var o, s = t(3);
r(), e.exports = {
init: r,
val: i
}
}, {
3: 3
}
],
9: [
function(t, e, n) {
var r = t(7);
e.exports = new r("__twttr")
}, {
7: 7
}
],
10: [
function(t, e, n) {
e.exports = ["hi", "zh-cn", "fr", "zh-tw", "msa", "fil", "fi", "sv", "pl", "ja", "ko", "de", "it", "pt", "es", "ru", "id", "tr", "da", "no", "nl", "hu", "fa", "ar", "ur", "he", "th", "cs", "uk", "vi", "ro", "bn"]
}, {}
],
11: [
function(t, e, n) {
function r(t) {
if (t && /^[\w_]{1,20}$/.test(t)) return t;
throw new Error("Invalid screen name")
}
function i(t, e) {
t.className += " " + e
}
function o(t) {
return t && "false" === t.toLowerCase()
}
function s(t) {
return st.getElementById(t)
}
function a(t) {
return t = t || A.event, t && t.preventDefault ? t.preventDefault() : t.returnValue = !1, t && t.stopPropagation ? t.stopPropagation() : t.cancelBubble = !0, !1
}
function u(t) {
var e = R && R.name ? R.name + " (@" + ut + ")" : "@" + ut;
return E ? void(C.title = _("View your profile on Twitter")) : t ? (i(O, "following"), void(C.title = _("You are following %{name} on Twitter", {
name: e
}))) : (O.className = O.className.replace(/ ?following/, ""), void(C.title = _("Fol…
&#13;
这里看起来似乎是与twitters安全服务器握手。
这样您的信息就会被加密。
如果启动握手,那么所有发生的事情都是JS正在使按钮变灰。
这个api决不会直接与网站互动,因此当您重新访问该网站时,为什么没有看到灰色按钮。
实际上,这很好地认为Twitter意味着保护您作为用户的隐私。
它还表明,Twitter已经决定采用不跟踪网站的路线,因此他们不会查找大量用户信息。
对于等待我的回答以及冗长的评论感到抱歉,这个必须发生在最近一个月,因为我上次使用Twitter按钮的经历,他们有cookie掉落,并没有你喜欢的网关它现在。