javascript - วิธีส่งตัวแปรจากไฟล์เทมเพลต jade ไปยังไฟล์สคริปต์?
ฉันกำลังมีปัญหากับตัวแปร (config) ที่ประกาศในไฟล์เทมเพลตเจด (index.jade) ซึ่งไม่ได้ถูกส่งไปยังไฟล์จาวาสคริปต์ ทำให้จาวาสคริปต์ของฉันเกิดข้อผิดพลาด นี่คือไฟล์ (views/index.jade):
h1 #{title}
script(src='./socket.io/socket.io.js')
script(type='text/javascript')
var config = {};
config.address = '#{address}';
config.port = '#{port}';
script(src='./javascripts/app.js')
นี่คือส่วนหนึ่งของไฟล์ app.js ของฉัน (ฝั่งเซิร์ฟเวอร์):
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.set('address', 'localhost');
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', function(req, res){
res.render('index', {
address: app.settings.address,
port: app.settings.port
});
});
if (!module.parent) {
app.listen(app.settings.port);
console.log("Server listening on port %d",
app.settings.port);
}
// Start my Socket.io app and pass in the socket
require('./socketapp').start(io.listen(app));
และนี่คือส่วนหนึ่งของไฟล์จาวาสคริปต์ของฉันที่เกิดข้อผิดพลาด (public/javascripts/app.js):
(function() {
var socket = new io.Socket(config.address, {port: config.port, rememberTransport: false});
ฉันกำลังรันเว็บไซต์ในโหมดพัฒนา (NODE_ENV=development) บน localhost (เครื่องของฉันเอง) ฉันกำลังใช้ node-inspector สำหรับดีบัก ซึ่งมันบอกฉันว่าตัวแปร config ไม่ได้ถูกกำหนดใน public/javascripts/app.js
มีไอเดียไหม?? ขอบคุณ!!
คำตอบ #1
มันสาย นิดหน่อย แต่ว่า...
script.
loginName="#{login}";
นี่ทำงานได้ดีในสคริปต์ของฉัน ใน Express ฉันกำลังทำสิ่งนี้:
exports.index = function(req, res){
res.render( 'index', { layout:false, login: req.session.login } );
};
ฉันคิดว่าเจดล่าสุดน่าจะต่างออกไป?
เมอร์ช
แก้ไข: เพิ่ม "." หลังสคริปต์เพื่อป้องกันการเตือนของ Jade
คำตอบ #2
#{} ใช้สำหรับการแทรกสตริงแบบ escape ซึ่งจะทำการ escape ข้อมูลที่ป้อนโดยอัตโนมัติ ดังนั้นจึงเหมาะสำหรับ สตริงธรรมดา มากก่าวัตถุ JS:
script var data = #{JSON.stringify(data)}
<script>var data = {"foo":"bar"} </script>
!{} ใช้สำหรับการแทรกโค้ดแบบ ไม่ถูกหนีตัวอักษร ซึ่งเหมาะสมมากกว่า สำหรับ วัตถุ:
script var data = !{JSON.stringify(data)}
<script>var data = {"foo":"bar"} </script>
คำเตือน: โค้ดที่ไม่ได้รับการป้องกันสามารถเป็นอันตราย คุณต้องมั่นใจว่าทำความสะอาดข้อมูลที่ผู้ใช้ป้อนเพื่อหลีกเลี่ยงการโจมตีแบบข้ามเว็บไซต์ (XSS)
เช่น:
{ foo: 'bar </script><script> alert("xss") //' }
จะกลายเป็น:
<script>var data = {"foo":"bar </script><script> alert("xss") //"}</script>
วิธีแก้ไขที่เป็นไปได้: ใช้ .replace(/<\//g, '<\\/')
script var data = !{JSON.stringify(data).replace(/<\//g, '<\\/')}
<script>var data = {"foo":"bar<\/script><script>alert(\"xss\")//"}</script>
แนวคิดคือเพื่อป้องกันไม่ให้ผู้โจมตี:
- แยกออกจากตัวแปร:
JSON.stringifyทำให้เครื่องหมายคำพูดต้องหนี - หลุดออกจากแท็กสคริปต์: หากตัวแปร contents (ซึ่งคุณอาจไม่สามารถควบคุมได้หากมาจากฐานข้อมูลเป็นตัวอย่าง) มีสตริง
</script>คำสั่ง replace จะจัดการมัน
https://github.com/pugjs/pug/blob/355d3dae/examples/dynamicscript.pug
คำตอบ #3
ในกรณีของฉัน ฉันพยายามที่จะส่งอ็อบเจ็กต์เข้าไปในเทมเพลตผ่านเส้นทางของ Express (คล้ายกับการตั้งค่าของ OP) จากนั้นฉันต้องการส่งอ็อบเจ็กต์นั้นเข้าไปในฟังก์ชันที่ฉันเรียกผ่านแท็กสคริปต์ในเทมเพลต Pug แม้ว่าคำตอบของ lagginreflex จะช่วยให้ฉันใกล้เคียง แต่สุดท้ายฉันก็ได้ผลลัพธ์ดังต่อไปนี้:
script.
var data = JSON.parse('!{JSON.stringify(routeObj)}');
funcName(data)
นี่ทำให้มั่นใจได้ว่าวัตถุถูกส่งเข้ามาตามที่คาดไว้ แทนที่จะต้องทำการดีซีเรียไลซ์ในฟังก์ชัน นอกจากนี้ คำตอบอื่น ๆ ดูเหมือนจะทำงานได้ดีกับค่าประเภทพื้นฐาน แต่เมื่อมีการส่งอาเรย์หรือสิ่งอื่น ๆ มาพร้อมกับวัตถุ มันจะถูกแปลงเป็นค่าข้อความ
