ค้นหาเว็บไซต์

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 = {&quot;foo&quot;:&quot;bar&quot;} </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>

แนวคิดคือเพื่อป้องกันไม่ให้ผู้โจมตี:

  1. แยกออกจากตัวแปร: JSON.stringify ทำให้เครื่องหมายคำพูดต้องหนี
  2. หลุดออกจากแท็กสคริปต์: หากตัวแปร 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)

นี่ทำให้มั่นใจได้ว่าวัตถุถูกส่งเข้ามาตามที่คาดไว้ แทนที่จะต้องทำการดีซีเรียไลซ์ในฟังก์ชัน นอกจากนี้ คำตอบอื่น ๆ ดูเหมือนจะทำงานได้ดีกับค่าประเภทพื้นฐาน แต่เมื่อมีการส่งอาเรย์หรือสิ่งอื่น ๆ มาพร้อมกับวัตถุ มันจะถูกแปลงเป็นค่าข้อความ

บทความที่เกี่ยวข้อง