javascript 单页应用程序无法获取 Facebook 共享的当前页面元标记
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23669640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
single page application can't get current page meta tag for facebook share
提问by John Lim
I'm trying to implement the facebook share button in my app, however I can't seem to get it to work on and idk why this is what I have so far.
我正在尝试在我的应用程序中实现 facebook 共享按钮,但是我似乎无法让它工作,并且不知道为什么这是我到目前为止所拥有的。
html(/post/some-random-string)
html(/post/some-random-string)
<div id="fb-root"></div>
<meta property="og:site_name" content="App">
<meta property="og:url" content="/post/{{data.permalink}}">
<meta property="og:title" content="{{data.title}}">
<meta property="og:type" content="blog">
<meta property="og:image" content="https://i1.ytimg.com/vi/tIWPnxEpNQg/maxresdefault.jpg">
<meta property="og:description" content="{{data.preview}}">
<body >
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=580882498674160&version=v2.0";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
// this facebook share button doesn't appear.
<div class="fb-share-button" data-href="https://developers.facebook.com/docs/plugins/" data-type="button"></div>
//so i manually make one.
<a href="" ng-click='facebookShare();'>Share</a>
</body>
controller.js
控制器.js
$scope.facebookShare= function(){
return window.open('http://www.facebook.com/sharer/sharer.php?u='+encodeURIComponent(location.href), 'facebook_share', 'height=320, width=640, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no');
}
it works however it didn't read the meta tag i have written above on the html page instead it reads from my index page
它可以工作,但是它没有读取我上面写在 html 页面上的元标记,而是从我的索引页面读取
index page
索引页
<!DOCTYPE html>
<html ng-app='app'>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<noscript>
<meta http-equiv="refresh" content="7">
<style type="text/css">
.pagecontainer {display:none;}
</style>
<div class="pure-u-1 text-center">
<title>Symsal- Oh no ! We need Javascript to work !</title>
<h3> Please Enable javascript </h3>
</div>
</noscript>
<head>
<title ng-bind='title'></title>
// some css file
</head>
<body>
<div class='puretype'>
<div ng-controller="MasterCtrl">
<div id="layout">
<!-- Menu toggle -->
<a href="" id="menuLink" class=" white menu-link">
<span></span>
</a>
<div id='menu' class="pure-u-1">
<div ng-bind-html="userView"></div>
</div>
</div>
<div class="pure-g-r">
<div id="feed-container" class='pure-u-1 slide'ng-view=''></div>
</div>
</div>
</div>
// some javascript files
</body>
</html>
facebook debugger
脸书调试器
回答by irukavina
What Hymanypan1989 said is true, you willhave to use the absolute url. But one other thing that I'm pretty sure happens is that Facebook won't run your JavaScript code, thus the part
Hymanypan1989 说的是真的,你将不得不使用绝对网址。但是我很确定会发生的另一件事是 Facebook 不会运行您的 JavaScript 代码,因此部分
<meta property="og:url" content="/post/{{data.permalink}}">
will never get replaced with
永远不会被取代
<meta property="og:url" content="/post/the-page-that-was-shared">
This problem that you are having could also prevent Google from crawling your page.
您遇到的这个问题也可能会阻止 Google 抓取您的网页。
We had the same problem, and we used https://prerender.ioto get around it. You can use it on your own server, or use one of their free/paid services.
我们遇到了同样的问题,我们使用https://prerender.io来解决它。您可以在自己的服务器上使用它,或者使用他们的免费/付费服务之一。
回答by Splaktar
You already have a body defined around your ng-view. Then your view has its own body. So you are trying to inject a body inside of a body which isn't going to do what you want.
您已经在 ng-view 周围定义了一个主体。那么你的视图就有了它自己的主体。所以你试图在一个身体内注入一个身体,这不会做你想做的。
Notice that your controller does not control the HTML element that contains the Meta tags. It only controls code that it contains (a div within the body in your case).
请注意,您的控制器不控制包含 Meta 标签的 HTML 元素。它只控制它包含的代码(在您的情况下是正文中的一个 div)。
You can add a controller to the HTML tag or you can use $rootScope.
您可以向 HTML 标记添加控制器,也可以使用 $rootScope。
Lots of answers to this here: How to dynamically change header based on AngularJS partial view?
这里有很多答案:How to dynamic change header based on AngularJS partial view?
In your controller that handles the ng-view:
app.controller('MainControl', function ($rootScope, $scope, Config) {
...
$rootScope.canonical = Config.domain;
});
在处理 ng-view 的控制器中:
app.controller('MainControl', function ($rootScope, $scope, Config) {
...
$rootScope.canonical = Config.domain;
});
I needed to dynamically set a canonical link, but the principal for metas is the same. In your header:
<link rel="canonical" ng-href="{{ canonical }}" />
我需要动态设置规范链接,但元数据的原则是相同的。在您的标题中:
<link rel="canonical" ng-href="{{ canonical }}" />
You'll probably want to use ng-bind
for a meta tag.
您可能想要ng-bind
用于元标记。
回答by Alex C
I would add to the previous answers that prerender will solve crawling problems but facebook share is a bit different I think ( feel free to prove me wrong :) ). To avoid annoying {{}}
you can define your own meta directive <meta meta-description>
and use a template:
我会在之前的答案中补充说 prerender 将解决爬行问题,但我认为 facebook share 有点不同(随时证明我错了:))。为了避免烦人,{{}}
您可以定义自己的元指令 <meta meta-description>
并使用模板:
app.directive('metaDescription', [ 'metaData', function(metaData){
return {
restrict: 'A',
replace: true,
template: '<meta name="description" content="{{metaData.pageDesc}}">',
link: function(scope,element){
scope.metaData = metaData;
}
};
}]);
We are still figuring out SEO/sharing issues with angularJS here but that's what we currently use.
我们仍在解决 angularJS 的 SEO/共享问题,但这就是我们目前使用的。
回答by Michael
I made it work using express. There may be some gaps in this, so if anyone tries it, feel free to fill in the gaps in the comments and I'll update...
我使用 express 让它工作了。这可能有一些空白,所以如果有人尝试过,请随时填写评论中的空白,我会更新......
I have both express and react running in two different consoles locally. For some reason, I only needed to run node on the express file in prod. Do whatever you need to to get it running. This will forward the request to the react server.
我在本地的两个不同控制台中同时运行了 express 和 react。出于某种原因,我只需要在 prod 中的 express 文件上运行 node。做任何你需要让它运行的事情。这会将请求转发到反应服务器。
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
Then I have a route for the pages that I share that looks something like this.
然后我有一个我共享的页面的路由,看起来像这样。
app.get('/details/:itemId', function(req, res) {
const fileName = path.join(__dirname, 'build', `${req.params.itemId}.html`);
var fileContents = fs.readFileSync(path.join(__dirname, 'build', 'index.html'), 'utf8');
fileContents = fileContents.replace("og tags", "new values");
fs.writeFileSync(fileName, fileContents);
res.sendFile(fileName);
});
You probably will want to search for the file and serve that up first if it exists so you aren't having problems with multiple clients writing to the same file at the same time in a high volume environment. Or better yet, do it in memory. Remember, order counts in express, so you really need to reverse the order of these two functions in your express file.
您可能希望搜索该文件并首先提供它(如果它存在),这样您就不会在高容量环境中遇到多个客户端同时写入同一个文件的问题。或者更好的是,在内存中进行。请记住,express 中的顺序很重要,因此您确实需要在 express 文件中颠倒这两个函数的顺序。
回答by Hymanypan1989
In your codes, you should set up your absolute url on attr 'data-href' of fb-share-button.
在您的代码中,您应该在 fb-share-button 的 attr 'data-href' 上设置绝对网址。
For example:
例如:
<div class='fb-share-button' data-href='https://yourabsoluteurl.com' data-type='button'>
</div>