ES6 টেম্পলেট আক্ষরিক রানটাইম (বা পুনঃব্যবহৃত) এ প্রতিস্থাপন করা যাবে?


129

tl; dr: পুনরায় ব্যবহারযোগ্য টেমপ্লেটকে কী আক্ষরিক করা সম্ভব?

আমি টেম্পলেট আক্ষরিক ব্যবহার করার চেষ্টা করছি কিন্তু আমার ধারণা আমি কেবল এটি পাই না এবং এখন আমি হতাশ হচ্ছি। আমার অর্থ, আমি মনে করি আমি এটি পেয়েছি তবে "এটি" কীভাবে এটি কাজ করে, বা এটি কীভাবে পাওয়া উচিত তা হওয়া উচিত নয়। এটি অন্যভাবে পাওয়া উচিত।

আমি যে সমস্ত উদাহরণ দেখি (এমনকি ট্যাগযুক্ত টেমপ্লেটগুলি) তারও দরকার যে "বিকল্পগুলি" ঘোষণার সময় করা উচিত এবং রান রান সময় নয়, যা কোনও টেমপ্লেটের জন্য আমার কাছে একেবারেই অকেজো বলে মনে হয়। হতে পারে আমি পাগল, তবে আমার কাছে একটি "টেমপ্লেট" হ'ল একটি নথিতে টোকেন রয়েছে যা আপনি যখন ব্যবহার করবেন তখন তা প্রতিস্থাপিত হয়, আপনি যখন এটি তৈরি করেন তা নয়, অন্যথায় এটি কেবল একটি দস্তাবেজ (অর্থাত্ একটি স্ট্রিং)। টোকেন হিসাবে টোকেনের সাথে একটি টেম্পলেট সংরক্ষণ করা হয় এবং যখন আপনি ... মূল্যায়ন করেন তখন সেই টোকেনগুলি মূল্যায়ন করা হয়।

প্রত্যেকে এর মতো একটি ভয়াবহ উদাহরণ উদ্ধৃত করে:

var a = 'asd';
return `Worthless ${a}!`

এটা সুন্দর, কিন্তু যদি আমি ইতিমধ্যে জানেন a, আমি would শুধু return 'Worthless asd'বা return 'Worthless '+a। আলোচ্য বিষয়টি কি? সিরিয়াসলি। ঠিক আছে বিন্দুটি অলসতা; কম প্লাস, আরও পঠনযোগ্যতা। গ্রেট। তবে এটি কোনও টেম্পলেট নয়! আইএমএইচও নয়। আর এমএইচও এটাই গুরুত্বপূর্ণ! আইএমএইচও সমস্যা হ'ল টেমপ্লেটটি ঘোষণার সাথে সাথে মূল্যায়ন করা হয়, তাই আপনি যদি করেন, আইএমএইচও:

var tpl = `My ${expletive} template`;
function go() { return tpl; }
go(); // SPACE-TIME ENDS!

যেহেতু expletiveঘোষিত হয়নি, এটি এর মতো কিছু করে My undefined template। সুপার. আসলে, কমপক্ষে ক্রোমে, আমি এমনকি টেমপ্লেটটিও ঘোষণা করতে পারি না; এটি ত্রুটি ছুড়ে দেয় কারণ expletiveসংজ্ঞায়িত হয়নি। আমার যা প্রয়োজন তা হ'ল টেমপ্লেটটি ঘোষণার পরে প্রতিস্থাপনটি করতে সক্ষম হওয়া:

var tpl = `My ${expletive} template`;
function go() { return tpl; }
var expletive = 'great';
go(); // My great template

তবে এটি কীভাবে সম্ভব তা আমি দেখতে পাচ্ছি না, কারণ এগুলি আসলে টেম্পলেট নয়। এমনকি আপনি যখন বলছেন আমার ট্যাগ, নোপ ব্যবহার করা উচিত, তারা কাজ করে না:

> explete = function(a,b) { console.log(a); console.log(b); }
< function (a,b) { console.log(a); console.log(b); }
> var tpl = explete`My ${expletive} template`
< VM2323:2 Uncaught ReferenceError: expletive is not defined...

এগুলি আমাকে বিশ্বাস করতে পরিচালিত করেছে যে টেমপ্লেটের আক্ষরিকগুলি ভয়াবহভাবে ভুল নাম দেওয়া হয়েছে এবং তাদের আসলে কী তা বলা উচিত: বংশগত । আমি অনুমান করি যে "আক্ষরিক" অংশটি আমার সম্পর্কে অবহিত হওয়া উচিত (যেমন, স্থায়ী)?

আমি কিছু অনুপস্থিত করছি? পুনরায় ব্যবহারযোগ্য টেম্পলেটকে আক্ষরিক করার জন্য কি কোনও (ভাল) উপায় আছে?


আমি আপনাকে দিচ্ছি, পুনরায় ব্যবহারযোগ্য টেম্পলেট আক্ষরিক :

> function out(t) { console.log(eval(t)); }
  var template = `\`This is
  my \${expletive} reusable
  template!\``;
  out(template);
  var expletive = 'curious';
  out(template);
  var expletive = 'AMAZING';
  out(template);
< This is
  my undefined reusable
  template!
  This is
  my curious reusable
  template!
  This is
  my AMAZING reusable
  template!

এবং এখানে একটি নিষ্পাপ "সহায়ক" ফাংশন ...

function t(t) { return '`'+t.replace('{','${')+'`'; }
var template = t(`This is
my {expletive} reusable
template!`);

... এটি "আরও ভাল" করতে।

আমি যে অঞ্চল থেকে তারা কুঁচকে যাওয়া অনুভূতি তৈরি করে সেগুলির কারণে আমি তাদেরকে টেমপ্লেট গেটেরাল বলতে আগ্রহী।


1
এটি স্ট্রাইকথ্রু সমর্থন করে (তবে এর মতো মন্তব্যে নয়)। আপনার পাঠ্য একটি <strike>ট্যাগ রাখুন ।
পয়েন্টি

ES6 টেম্পলেট আক্ষরিকাগুলি বেশিরভাগ পুরানো ফ্যাশন স্ট্রিং অন্তরঙ্গকরণের জন্য। আপনি যদি গতিশীল টেম্পলেটগুলি হ্যান্ডেলবারস ইত্যাদি ব্যবহার করতে চান তবে পয়েন্টির ট্যাগযুক্ত টেম্পলেট সমাধান।
জুইস 2'15


8
আপনি কি দয়া করে আপনার পোস্টকে কিছুটা কম শব্দ করতে পারেন? এছাড়া, এটিও মনে হচ্ছে আপনি Q & A- বিন্যাসে একটি টিউটোরিয়াল লিখতে, যদি আপনি তা-ই করলেন, "দয়া করে সরিয়ে দেয়ার উদ্দেশ্যে করা হচ্ছে আমি পেশ করছি ... আপনার থেকে" অংশ প্রশ্ন এবং উত্তর যেমন পোষ্ট
বার্গি

আমি এখানে অনেক ভাল উত্তর আছে লক্ষ্য। সম্ভবত একটি গ্রহণ।
অবল্টার

উত্তর:


86

এই লিটারেলগুলিকে অন্যান্য টেম্পলেট ইঞ্জিনগুলির মতো কাজ করতে একটি মধ্যস্থতাকারী ফর্ম থাকা দরকার।

এটি করার সর্বোত্তম উপায়টি হল Functionকনস্ট্রাক্টর ব্যবহার করা ।

const templateString = "Hello ${this.name}!";
const templateVars = {
    name: "world"    
}

const fillTemplate = function(templateString, templateVars){
    return new Function("return `"+templateString +"`;").call(templateVars);
}

console.log(fillTemplate(templateString, templateVars));

অন্যান্য টেম্পলেট ইঞ্জিনগুলির মতো আপনিও অন্য কোনও স্থানের মতো ফাইলের স্ট্রিংটি পেতে পারেন।

এই পদ্ধতিটি ব্যবহার করার মতো সমস্যা থাকতে পারে যেমন টেমপ্লেট ট্যাগগুলি ব্যবহার করা শক্ত, তবে আপনি যদি চালাক হন তবে সেগুলি যুক্ত করা যেতে পারে। দেরী বিক্ষোভের কারণে আপনারও ইনলাইন জাভাস্ক্রিপ্ট যুক্তি থাকতে পারে না। এটি কিছু চিন্তা দিয়ে প্রতিকারও করা যেতে পারে।


8
নিস! আপনি এমনকি ব্যবহার করতে পারেনnew Function(`return \`${template}\`;`)
রুবেন স্টলক

এবং এই টেম্পলেটগুলি কোনও পদ্ধতিতে কল করে বা অন্য কোনও টেমপ্লেটের সংকলিত ফলাফলটি দিয়ে পাস করে আর্গুমেন্টের মাধ্যমে তৈরি বা "অন্তর্ভুক্ত" হতে পারে।
কোয়ান্টিন এঙ্গেলস

কোয়ান্টিন 'টেমপ্লেট ট্যাগগুলি' বলতে কী বোঝায়? ধন্যবাদ!
মাইকমেকানা

10
সাবধান হোন যে এই টেমপ্লেটটি স্ট্রিংটি প্রতিস্থাপনের (যেমন ওয়েবপ্যাক) প্রতি 'লুক্কায়িত' এবং এটি ক্লায়েন্ট-সাইডের পর্যাপ্ত সামঞ্জস্যপূর্ণ কোনও (অর্থাৎ আই 11) কোনও জায়গায় স্থানান্তরিত করবে না ...!
ফ্রাঙ্ক নোক্কে


65

আপনি কোনও ফাংশনে একটি টেম্পলেট স্ট্রিং রাখতে পারেন:

function reusable(a, b) {
  return `a is ${a} and b is ${b}`;
}

আপনি ট্যাগ টেম্পলেট দিয়ে একই জিনিস করতে পারেন:

function reusable(strings) {
  return function(... vals) {
    return strings.map(function(s, i) {
      return `${s}${vals[i] || ""}`;
    }).join("");
  };
}

var tagged = reusable`a is ${0} and b is ${1}`; // dummy "parameters"
console.log(tagged("hello", "world"));
// prints "a is hello b is world"
console.log(tagged("mars", "jupiter"));
// prints "a is mars b is jupiter"

ধারণাটি হ'ল টেমপ্লেট পার্সারটিকে পরিবর্তনশীল "স্লটগুলি" থেকে ধ্রুবক স্ট্রিংগুলি বিভক্ত করতে দেওয়া হবে এবং তারপরে একটি ফাংশন ফিরিয়ে দেওয়া হবে যা প্রতিটি বারের মানগুলির একটি নতুন সেটের ভিত্তিতে এটি আবার একসাথে প্যাচ করে।


3
@ ফেলিক্সক্লিং যা হতে পারে; আমি যদি তা হয় তা পরীক্ষা করে ঠিক করে দেব। হ্যাঁ সম্পাদনা করুন দেখে মনে হচ্ছে যে উদাহরণের একটি উল্লেখযোগ্য অংশ আমি রেখেছি, এটি "পুনরায় ব্যবহারযোগ্য" ফাংশন হ'ল :)
পয়েন্টি

@ ফেলিক্সক্লিং আমি কী করব তা নিশ্চিত নই কারণ আমি তখন যা ভাবছিলাম তা মোটেও মনে করতে পারি না!
পয়েন্টি

1
হ্যাঁ, এটা অনেক জানার জন্য না পারেন tbh হতে;) আপনি সবসময় অপসারণ করতে পারেন .... কিন্তু reusableযাতে এটি একটি ফাংশন ফেরৎ বাস্তবায়ন করা যেতে পারে, এবং আপনি ব্যবহার করতে চাই ${0}এবং ${1}পরিবর্তে আক্ষরিক ভিতরে ${a}এবং ${b}। তারপরে আপনি সেই মানগুলি ফাংশনের আর্গুমেন্টগুলি উল্লেখ করতে ব্যবহার করতে পারেন, বার্গি তার শেষ উদাহরণে যা করেছেন তার সমান: স্ট্যাকওভারফ্লো.com / a / 22619256 / 218196 (অথবা আমি অনুমান করি এটি মূলত একই)।
ফেলিক্স ক্লিং 25:38

1
@ ফেলিক্সকলিং ঠিক আছে আমি মনে করি যে আমি এমন কিছু নিয়ে এসেছি যা কমপক্ষে অস্পষ্টভাবে ওপি এর লাইনে বরাবর।
পয়েন্টি

3
যদি ফলাফলটি আসলে স্ট্রিং না হয় তবে ট্যাগযুক্ত টেমপ্লেটগুলি সত্যই শক্তিশালী হতে পারে। উদাহরণস্বরূপ আমার এক প্রকল্পে আমি এটিটি নোড ইন্টারপোলেশন করতে ব্যবহার করি। যেমন expression`a + ${node}`একটি বিদ্যমান এএসটি নোডের সাথে বাইনারিএক্সপ্রেসন নোড তৈরি করতে পারে node। অভ্যন্তরীণভাবে আমরা বৈধ কোড উত্পন্ন করতে একটি স্থানধারক সন্নিবেশ করি, এটিটি একটি এএসটি হিসাবে বিশ্লেষণ করে এবং স্থানধারককে মান দিয়ে পাস করা প্রতিস্থাপন করি।
ফেলিক্স ক্লিংং

45

সম্ভবত এটি করার সর্বোত্তম উপায় হ'ল তীর ফাংশনগুলি (কারণ এই মুহুর্তে, আমরা ইতিমধ্যে ES6 ব্যবহার করছি)

var reusable = () => `This ${object} was created by ${creator}`;

var object = "template string", creator = "a function";
console.log (reusable()); // "This template string was created by a function"

object = "example", creator = "me";
console.log (reusable()); // "This example was created by me"

... এবং ট্যাগ টেম্পলেট আক্ষরিক জন্য:

reusable = () => myTag`The ${noun} go ${verb} and `;

var noun = "wheels on the bus", verb = "round";
var myTag = function (strings, noun, verb) {
    return strings[0] + noun + strings[1] + verb + strings[2] + verb;
};
console.log (reusable()); // "The wheels on the bus go round and round"

noun = "racecars", verb = "fast";
myTag = function (strings, noun, verb) {
    return strings[0] + noun + strings[1] + verb;
};
console.log (reusable()); // "The racecars go fast"

এটি কম্পাইলারগুলির সাথে সমস্যা সৃষ্টি করতে পারে এবং প্রচুর মন্দার কারণ হতে পারে eval()বা এর ব্যবহার এড়িয়ে যায় Function()


আমি মনে করি এটি একটি সেরা কারণ আপনি myTagকিছু জিনিস করতে ফাংশনের অভ্যন্তরে কিছু কোড ইনজেক্ট করতে পারেন। উদাহরণস্বরূপ, আউটপুট ক্যাশে করার জন্য ইনপুট প্যারামগুলি কী হিসাবে ব্যবহার করুন।
বাহ

আমি মনে করি এটিই সেরা উত্তর। এছাড়াও আপনি তীর ফাংশন যা আমি মনে করে তোলে এটা এমনকি ক্লিনার প্যারামিটার যোগ করতে পারেন: var reusable = (value: string) => `Value is ${value}`
haggisandchips

13

2019 উত্তর :

দ্রষ্টব্য : গ্রন্থাগারটি XSS এড়ানোর জন্য ব্যবহারকারীরা স্ট্রিং স্যানিটাইজ করার প্রত্যাশা করেছিল। গ্রন্থাগারের 2 সংস্করণটির আর ব্যবহারকারীর স্ট্রিংগুলি স্যানিটাইজ করার প্রয়োজন নেই (যা ওয়েব বিকাশকারীদের যাইহোক করা উচিত) কারণ এটি evalসম্পূর্ণ এড়ানো যায় ।

es6-dynamic-templateNpm উপর মডিউল এই আছে।

const fillTemplate = require('es6-dynamic-template');

বর্তমান উত্তরগুলি থেকে পৃথক:

  • এটি ES6 টেম্পলেট স্ট্রিং ব্যবহার করে, অনুরূপ বিন্যাস নয়। ব্যবহারকারীদের অচিহ্নহীন ইনপুট স্ট্রিংগুলি ব্যবহার করা থেকে বিরত রাখতে সংস্করণ 2 আপডেট করুন ES6 টেম্পলেট স্ট্রিংয়ের পরিবর্তে অনুরূপ ফর্ম্যাট ব্যবহার করে।
  • এটি thisটেম্পলেট স্ট্রিংয়ের প্রয়োজন নেই
  • আপনি একক ফাংশনে টেম্পলেট স্ট্রিং এবং ভেরিয়েবল নির্দিষ্ট করতে পারেন
  • এটি স্ট্যাকওভারফ্লো থেকে কপিপাস্টার পরিবর্তে একটি রক্ষণাবেক্ষণযোগ্য, আপডেটযোগ্য মডিউল

ব্যবহার সহজ। একক উদ্ধৃতি ব্যবহার করুন কারণ টেম্পলেট স্ট্রিংটি পরে সমাধান করা হবে!

const greeting = fillTemplate('Hi ${firstName}', {firstName: 'Joe'});

আপনি যদি এটি রিএ্যাক্ট নেটিভের সাথে ব্যবহার করেন তবে এটি অ্যান্ড্রয়েডে বিশেষভাবে ভেঙে যাবে। অ্যান্ড্রয়েড নোড রানটাইম গতিশীল টেম্পলেটগুলি সমর্থন করে না, কেবল পূর্বনির্ধারিতগুলি
অলিভার ডিকসন

1
এটি আমার ব্যক্তিগত প্রকল্পগুলিতে আমি একটি সমাধান এবং এটি নির্দোষভাবে কাজ করে। আমি আসলে খুব বেশি লাইব্রেরি বিশেষত এর মতো ছোট ছোট ব্যবহারের জন্য ব্যবহার করা খারাপ ধারণা বলে মনে করি।
অলিভার ডিকসন

1
এক্সএসএস দুর্বলতা ? এই FIDDLE এ
কামিল কিয়েসজেউস্কি

1
@ কামিল কেবল এক্সএসএস করুন যদি আপনি ক) ব্যবহারকারীদের তৈরি করার ক্ষমতা দেন খ) ইনপুট স্ট্রিংগুলিকে স্যানিটাইজ করবেন না। আমি একটি সতর্কতা যুক্ত করব যে লোকেরা যদিও ব্যবহারকারীদের ইনপুট স্যানিটাইজ করতে পারে।
মাইকম্যাকানা

1
এটি দূরবর্তী অবস্থান থেকে এস 6 টেম্পলেট আক্ষরিক ব্যবহার করে না। 10 * 20 = ${10 * 20}এটি চেষ্টা করুন যাতে এটি একইরকম ফর্ম্যাট হতে পারে তবে এটি দূরবর্তী থেকে এস 6 টেম্পলেট লিটারালগুলিও নয়
gman

12

হ্যাঁ আপনি আপনার স্ট্রিংটিকে টেম্পলেট দিয়ে পার্টিশন করে JS হিসাবে Function(বা eval) দ্বারা ভাগ করে নিতে পারেন - তবে এটি প্রস্তাবিত নয় এবং এক্সএসএস আক্রমণকে অনুমতি দিন

পরিবর্তে আপনি নিরাপদে গতিশীল উপায়ে objটেমপ্লেটে অবজেক্ট ক্ষেত্রগুলি সন্নিবেশ করতে পারেনstr

let inject = (str, obj) => str.replace(/\${(.*?)}/g, (x,g)=> obj[g]);


এই পদ্ধতিটি আমি ব্যবহার করি এটি ভালভাবে কাজ করে। ভালো উদাহরণ! না? * রেজিএক্সে * সাহায্যের পরে কি? আমি কোনও রেজিএক্স বিশেষজ্ঞ নই, তবে অনুমান করছি যেহেতু * মানে শূন্য বা তার বেশি (এবং আপনি এই ক্ষেত্রে "আরও" চান) তাই লোভী বাধা দেওয়ার দরকার নেই?
Gen1-1

@ জেন ১-১ .*?মানে অ-লোভী - আপনি যদি সরিয়ে ফেলেন "?"তবে স্নিপেট ভুল ফল দেবে
কামিল কিয়েসজেউস্কি

তুমি সঠিক, আমার ভুল। আমি আমার টেম্পলেটগুলিতে use ব্যবহার করি না এবং RegEx: / {(\ w *)} / g ব্যবহার করি কারণ আমার ট্যাগে কখনও ফাঁকা থাকে না, তবে। *? কাজ করে। আমি ব্যবহার:function taggedTemplate(template, data, matcher) { if (!template || !data) { return template; } matcher = matcher || /{(\w*)}/g; // {one or more alphanumeric characters with no spaces} return template.replace(matcher, function (match, key) { var value; try { value = data[key] } catch (e) { // } return value || ""; }); }
Gen1-1

@ Gen1-1- তেও কি নেস্টেড ডেটা সম্ভব? পছন্দ data = { a: 1, b: { c:2, d:3 } }-> b.c?
muescha

1
@ মুছেছা আপনি লাইনটি পরিবর্তন করবেন: মান = ডেটা [কী], পুনরাবৃত্তি ব্যবহার করতে এবং সম্পত্তিটি না পাওয়া পর্যন্ত আপনার পুরো ডেটা অবজেক্ট এবং নেস্টেড অবজেক্টগুলি অনুসন্ধান করতে। উদাহরণ: codereview.stackexchange.com/questions/73714/... এবং mikedoesweb.com/2016/es6-depth-first-object-tree-search
Gen1-1

9

@Metamorphasi এর দেওয়া উত্তর সরলকরণ;

const fillTemplate = function(templateString, templateVars){
  var func = new Function(...Object.keys(templateVars),  "return `"+templateString +"`;")
  return func(...Object.values(templateVars));
}

// Sample
var hosting = "overview/id/d:${Id}";
var domain = {Id:1234, User:22};
var result = fillTemplate(hosting, domain);

console.log(result);


এই কোডটি নেতৃস্থানীয় উত্তরের চেয়ে বেশি স্ব-ব্যাখ্যা করছে। আমার আপ-ভোট পেয়েছে :)
ymz

এটি আপনাকে পরিবর্তনশীল বা বাহ্যিক ফাইলগুলি (নোডজেএসে) টেমপ্লেট হিসাবে ব্যবহার করার বা রান-টাইমে এগুলিকে গতিশীলভাবে তৈরি করার অনুমতি দেয়। ব্যবহার ছাড়া eval
b01

এক্সএসএস দুর্বলতা ? দূষিত কোড সহ ভিজিট (পরিবর্তনশীল var hosting) এখানে
কামিল কিয়েসজেউস্কি

7

আপনি আদেশ পরামিতি বা প্রসঙ্গ / নামব্যবধান ব্যবহার করার জন্য আপনার টেমপ্লেট মধ্যে ভেরিয়েবল রেফারেন্স না চাইলে যেমন ${0}, ${this.something}অথবা ${data.something}, আপনি একটি টেমপ্লেট ফাংশন যা আপনার জন্য scoping যত্ন নেয় থাকতে পারে।

আপনি কীভাবে এই জাতীয় টেম্পলেট কল করতে পারেন তার উদাহরণ :

const tempGreet = Template(() => `
  <span>Hello, ${name}!</span>
`);
tempGreet({name: 'Brian'}); // returns "<span>Hello, Brian!</span>"

টেমপ্লেট ফাংশন:

function Template(cb) {
  return function(data) {
    const dataKeys = [];
    const dataVals = [];
    for (let key in data) {
      dataKeys.push(key);
      dataVals.push(data[key]);
    }
    let func = new Function(...dataKeys, 'return (' + cb + ')();');
    return func(...dataVals);
  }
}

এই ক্ষেত্রে উদ্ভট হ'ল আপনাকে কেবল একটি ফাংশন পাস করতে হবে (উদাহরণস্বরূপ আমি একটি তীর ফাংশন ব্যবহার করেছি) যা ES6 টেমপ্লেটকে আক্ষরিক প্রত্যাবর্তন করে। আমি মনে করি আমরা যে ধরণের পুনঃব্যবহারযোগ্য ইন্টারপোলেশন পরে আছি এটি একটি সামান্য বাণিজ্য।

এটি এটি গিটহাবে রয়েছে: https://github.com/Adelphos/ES6- পুনঃব্যবহারযোগ্য- আলোচনা


3
এই ভাল, কিন্তু minification (Vals, func, ইত্যাদি) unnecessaery হয়, 'CB' একটি কলব্যাক (এই সম্পূর্ণভাবে সিঙ্ক কোড) হয় না, এবং আপনি শুধু ব্যবহার করতে পারেন Object.values()এবংObject.keys()
mikemaccana

3

সংক্ষিপ্ত উত্তরটি হ'ল লোডাসে _.টেমলেট ব্যবহার করুন

// Use the ES template literal delimiter as an "interpolate" delimiter.
// Disable support by replacing the "interpolate" delimiter.
var compiled = _.template('hello ${ user }!');
compiled({ 'user': 'pebbles' });
// => 'hello pebbles!'

3

আমি কিছু অনুপস্থিত করছি? পুনরায় ব্যবহারযোগ্য টেমপ্লেটকে আক্ষরিক করার জন্য কি কোনও [ভাল] উপায় আছে?

হয়তো আমি কিছু মিস করছি, কারণ আমার এই সমস্যার সমাধানটি আমার কাছে এতটাই সুস্পষ্ট বলে মনে হয়েছে যে আমি খুব অবাক হয়েছি যে কেউ ইতিমধ্যে এমন একটি পুরানো প্রশ্নে লিখেনি।

আমার এটির জন্য প্রায় এক-লাইনার রয়েছে:

function defer([first, ...rest]) {
  return (...values) => rest.reduce((acc, str, i) => acc + values[i] + str, first);
}

এখানেই শেষ. যখন আমি কোনও টেম্পলেট পুনরায় ব্যবহার করতে এবং বিকল্পগুলির সমাধানটি স্থগিত করতে চাই, তখন আমি কেবল এটি করি:

> t = defer`My template is: ${null} and ${null}`;
> t('simple', 'reusable');          // 'My template is: simple and reusable'
> t('obvious', 'late to the party'; // 'My template is: obvious and late to the party'
> t(null);                          // 'My template is: null and undefined'
>
> defer`Choose: ${'ignore'} / ${undefined}`(true, false); // 'Choose: true / false'

এই ট্যাগ প্রয়োগ করে আ 'function'(আ এর পরিবর্তে 'string') ফিরে আসবে যা আক্ষরিকের কাছে দেওয়া কোনও পরামিতি উপেক্ষা করে। তারপরে এটি পরে নতুন পরামিতিগুলির সাথে কল করা যেতে পারে। যদি কোনও প্যারামিটারের সাথে সম্পর্কিত কোনও প্রতিস্থাপন না থাকে তবে তা হয়ে যায় 'undefined'


বর্ধিত উত্তর

এই সাধারণ কোডটি কার্যকরী, তবে আপনার যদি আরও বিস্তৃত আচরণের প্রয়োজন হয় তবে একই যুক্তি প্রয়োগ করা যেতে পারে এবং অবিরাম সম্ভাবনা রয়েছে। আপনি করতে পারেন:

  1. মূল পরামিতি ব্যবহার করুন:

আপনি নির্মাণে আক্ষরিক অর্থে দেওয়া মূল মানগুলি সংরক্ষণ করতে পারেন এবং টেমপ্লেট প্রয়োগ করার সময় সেগুলি সৃজনশীল উপায়ে ব্যবহার করতে পারেন। তারা পতাকা, টাইপ বৈধকারক, ফাংশন ইত্যাদি হতে পারে এটি এটি একটি উদাহরণ যা তাদের ডিফল্ট মান হিসাবে ব্যবহার করে:

    function deferWithDefaults([first, ...rest], ...defaults) {
      return (...values) => rest.reduce((acc, curr, i) => {
        return acc + (i < values.length ? values[i] : defaults[i]) + curr;
      }, first);
    }

তারপর:

    > t = deferWithDefaults`My template is: ${'extendable'} and ${'versatile'}`;
    > t('awesome');                 // 'My template is: awesome and versatile' 
  1. একটি টেম্পলেট কারখানা লিখুন:

এই যুক্তিটিকে এমন কোনও ফাংশনে আবৃত করে যা প্রত্যাশা করে, যুক্তি হিসাবে, একটি কাস্টম ফাংশন যা হ্রাসে প্রয়োগ করা যেতে পারে (যখন টেমপ্লেটের আক্ষরিক টুকরোতে যোগ দেওয়ার সময়) এবং কাস্টম আচরণের সাথে একটি নতুন টেম্পলেট ফেরত দেয়।

    const createTemplate = fn => function (strings, ...defaults) {
      const [first, ...rest] = strings;
      return (...values) => rest.reduce((acc, curr, i) => {
        return acc + fn(values[i], defaults[i]) + curr;
      }, first);
    };

তারপরে আপনি যেমন টেমপ্লেট লিখতে পারেন যা এম্বেডড এইচটিএমএল, সিএসএস, এসকিউএল, বাশ লিখার সময় প্যারামিটারগুলি স্বয়ংক্রিয়ভাবে পালাতে বা স্যানিটাইজ করতে পারে ...

    function sqlSanitize(token, tag) {
      // this is a gross simplification, don't use in production.
      const quoteName = name => (!/^[a-z_][a-z0-9_$]*$/.test(name) ? `"${name.replace(/"/g, '""')}"` : name);
      const quoteValue = value => (typeof value == 'string' ? `'${value.replace(/'/g, "''")}'` : value);
      switch (tag) {
        case 'table':
          return quoteName(token);
        case 'columns':
          return token.map(quoteName);
        case 'row':
          return token.map(quoteValue);
        default:
          return token;
      }
    }

    const sql = createTemplate(sqlSanitize);

এই নির্দোষ (আমি পুনরাবৃত্তি, ভুতু! ) এসকিউএল টেম্পলেট দিয়ে আমরা এর মতো প্রশ্ন তৈরি করতে পারি:

    > q  = sql`INSERT INTO ${'table'} (${'columns'})
    ... VALUES (${'row'});`
    > q('user', ['id', 'user name', 'is"Staff"?'], [1, "O'neil", true])
    // `INSERT INTO user (id,"user name","is""Staff""?")
    // VALUES (1,'O''neil',true);`
  1. প্রতিস্থাপনের জন্য নামযুক্ত পরামিতিগুলি গ্রহণ করুন: ইতিমধ্যে যা দেওয়া হয়েছিল তার উপর ভিত্তি করে একটি কঠোর অনুশীলন নয়। এই অন্যান্য উত্তরে একটি বাস্তবায়ন আছে ।

  2. রিটার্ন অবজেক্টটিকে এর মতো আচরণ করুন 'string': আচ্ছা, এটি বিতর্কিত তবে আকর্ষণীয় ফলাফলের দিকে নিয়ে যেতে পারে। এই অন্য উত্তরে দেখানো হয়েছে ।

  3. কল সাইটে বিশ্বব্যাপী নেমস্পেসের মধ্যে প্যারামিটারগুলি সমাধান করুন:

আমি আপনাকে দিচ্ছি, পুনরায় ব্যবহারযোগ্য টেম্পলেট আক্ষরিক:

ঠিক আছে, ওপি হ'ল তার সংযোজনটি হ'ল কমান্ডটি ব্যবহার করে evil, আমি বলতে চাইছি eval। এই ছাড়া করা যেতে পারে eval, শুধু বিশ্বব্যাপী (অথবা উইন্ডো) বস্তুর মধ্যে পাস পরিবর্তনশীল নাম অনুসন্ধান করে। এটি কীভাবে করব তা আমি দেখাব না কারণ এটি আমার পছন্দ নয়। বন্ধগুলি সঠিক পছন্দ।


2

এটি আমার সেরা চেষ্টা:

var s = (item, price) => {return `item: ${item}, price: $${price}`}
s('pants', 10) // 'item: pants, price: $10'
s('shirts', 15) // 'item: shirts, price: $15'

সাধারণকরণের জন্য:

var s = (<variable names you want>) => {return `<template with those variables>`}

আপনি যদি E6 চালাচ্ছেন না, আপনি এটি করতেও পারেন:

var s = function(<variable names you want>){return `<template with those variables>`}

এটি পূর্ববর্তী উত্তরের চেয়ে কিছুটা সংক্ষিপ্ত বলে মনে হচ্ছে।

https://repl.it/@abalter/reusable-JS-template-literal


2

সাধারণভাবে আমি মন্দ ব্যবহারের বিরুদ্ধে eval(), তবে এক্ষেত্রে এটি বোধগম্য হয়:

var template = "`${a}.${b}`";
var a = 1, b = 2;
var populated = eval(template);

console.log(populated);         // shows 1.2

তারপরে আপনি যদি মানগুলি পরিবর্তন করেন এবং আবার eval () কল করেন তবে আপনি নতুন ফলাফল পাবেন:

a = 3; b = 4;
populated = eval(template);

console.log(populated);         // shows 3.4

যদি আপনি এটি কোনও ফাংশনে চান, তবে এটি এমনভাবে লেখা যেতে পারে:

function populate(a, b){
  return `${a}.${b}`;
}

আপনি যদি কোনও ফাংশন লিখছেন যাতে টেমপ্লেট অন্তর্ভুক্ত থাকে তবে আপনার অবশ্যই ব্যবহার করা উচিত নয় eval
বার্গি

@ বারগি কেন? আপনার বাস্তবায়ন থেকে এটি কীভাবে আলাদা?
ইস্পির

2
যে কারণগুলি আমি "জানি" বলে মনে হয় তা যে কোনও গতিশীলভাবে নির্মিত কোডটিতে প্রযোজ্য। ফাংশনটি লিখতে যাতে এটি eval()স্পষ্টভাবে কল না করে ফলাফল তৈরি করে ঠিক ঠিক তেমনই eval()হ'ল এতে কোনও লাভ নেই কারণ এটি কেবল কোডটি পড়া শক্ত করে।
ইস্পির

1
যথাযথভাবে। এবং যেহেতু আপনার populateফাংশনটি গতিশীলভাবে কোডটি তৈরি করে না তাই evalএটির সমস্ত ত্রুটিগুলি ব্যবহার করা উচিত নয় ।
বার্গি

6
আপনার ফাংশনটি কেবল function populate(a,b) { return `${a}.${b}`; }
alভাল

1

আপডেট করা: নিম্নলিখিত উত্তরগুলি একক ভেরিয়েবল নামের মধ্যে সীমাবদ্ধ, সুতরাং, টেমপ্লেটগুলি: 'Result ${a+b}'এই ক্ষেত্রে কার্যকর নয়। তবে আপনি সর্বদা টেম্পলেট মানগুলির সাথে খেলতে পারেন:

format("This is a test: ${a_b}", {a_b: a+b});

মূল উত্তর:

পূর্ববর্তী উত্তরের ভিত্তিতে তবে আরও একটি "বন্ধুত্বপূর্ণ" ইউটিলিটি ফাংশন তৈরি করে:

var format = (template, params) => {
    let tpl = template.replace(/\${(?!this\.)/g, "${this.");
    let tpl_func = new Function(`return \`${tpl}\``);

    return tpl_func.call(params);
}

আপনি এটি ঠিক যেমন চালান করতে পারেন:

format("This is a test: ${hola}, second param: ${hello}", {hola: 'Hola', hello: 'Hi'});

এবং ফলস্বরূপ স্ট্রিংটি হওয়া উচিত:

'This is a test: Hola, second param: Hi'

এই জাতীয় টেম্পলেট সম্পর্কে কি? `Result: ${a+b}`
আতিরিস

1
হাই @ আতিরিস, আপনি ঠিক বলেছেন, এটি একটি সীমাবদ্ধতা, আমি আমার উত্তর আপডেট করেছি।
রবার্তো

1

আপনি যদি কিছু সহজ খুঁজছেন (কেবলমাত্র স্থির পরিবর্তনশীল ক্ষেত্রগুলি, কোনও গণনা, শর্তসাপেক্ষ ...) তবে এটি IE 8,9,10,11 এর মতো টেম্পলেট স্ট্রিং সমর্থন ব্যতীত ব্রাউজারগুলিতে ক্লায়েন্ট- সাইডও কাজ করে ...

এখানে আমরা যাচ্ছি:

fillTemplate = function (templateString, templateVars) {
    var parsed = templateString;
    Object.keys(templateVars).forEach(
        (key) => {
            const value = templateVars[key]
            parsed = parsed.replace('${'+key+'}',value)
        }
    )
    return parsed
}

এটি প্রতিটি চলকটির জন্য একটি অনুসন্ধান করবে। অন্য উপায় আছে যা একবারে সমস্ত ঘটনাকে প্রতিস্থাপন করে যা আমি এই মডিউলটিতে প্রয়োগ করেছি: নিরাপদ- es6-টেম্পলেট
আলেেক্স গবি

1

আমি টাইপ করার প্রয়োজন অতিরিক্ত অতিরেক এ বিরক্ত this.প্রত্যেক সময়, তাই আমিও মত ভেরিয়েবল প্রসারিত করতে Regex যোগ .aকরার this.a

সমাধান:

const interp = template => _thisObj =>
function() {
    return template.replace(/\${([^}]*)}/g, (_, k) =>
        eval(
            k.replace(/([.a-zA-Z0-9$_]*)([a-zA-Z0-9$_]+)/, (r, ...args) =>
                args[0].charAt(0) == '.' ? 'this' + args[0] + args[1] : r
            )
        )
    );
}.call(_thisObj);

যেমন ব্যবহার করুন:

console.log(interp('Hello ${.a}${.b}')({ a: 'World', b: '!' }));
// outputs: Hello World!

1

আমি কেবল একটি এনপিএম প্যাকেজ প্রকাশ করি যা কেবল এই কাজটি করতে পারে। গভীরভাবে অনুপ্রাণিত এই উত্তর

const Template = require('dynamic-template-string');

var tpl = new Template('hello ${name}');

tpl.fill({name: 'world'}); // ==> 'hello world';
tpl.fill({name: 'china'}); // ==> 'hello china';

এটি বাস্তবায়ন মারাত্মক সহজ। আপনি এটি পছন্দ করবেন আশা করি।


module.exports = class Template {
  constructor(str) {
    this._func = new Function(`with(this) { return \`${str}\`; }`);
  }

  fill(data) {
    return this._func.call(data);
  }
}

1

আপনি এর মতো ইনলাইন তীর ফাংশনটি ব্যবহার করতে পারেন, সংজ্ঞা:

const template = (substitute: string) => `[^.?!]*(?<=[.?\s!])${substitute}(?=[\s.?!])[^.?!]*[.?!]`;

ব্যবহার:

console.log(template('my replaced string'));

1

রানটাইম টেম্পলেট স্ট্রিং

var templateString = (template, values) => {
    let output = template;
    Object.keys(values)
        .forEach(key => {
        output = output.replace(new RegExp('\\$' + `{${key}}`, 'g'), values[key]);
    });
    return output;
};

পরীক্ষা

console.debug(templateString('hello ${word} world', {word: 'wonderful'}));

0

const fillTemplate = (template, values) => {
  template = template.replace(/(?<=\${)\w+(?=})/g, v=>"this."+v);
  return Function.apply(this, ["", "return `"+template+"`;"]).call(values);
};

console.log(fillTemplate("The man ${man} is brother of ${brother}", {man: "John", brother:"Peter"}));
//The man John is brother of Peter

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.