解析JSON文件后,如何从index.html获取值并将其用于呈现第二个模板?

问题描述

我正在努力将gulp和现代JavaScript捆绑在一起。


该应用程序非常简单:

  1. 用户显示一个html页面,他必须在其中检查一些单选按钮。
  2. 然后,用户单击按钮提交选择。
  3. 选择提交时,必须解析一个JSON文件,以便在20个可能的html页面显示一个

我具有以下(简化的)结构:

dist/
    index.html
src/
    scripts/
          main.js
          modules/
                 dispatchForm.js
    styles/  
          index.scss
    templates/
          index.pug
          partials/
                  default.pug
                  selectors.pug
gulpfile.js
data.json

在我的gulpfile.js中,我有

const bundler = () => {
  return rollup({
    input: './src/scripts/main.js',plugins: [
      babel(pkg.babel),nodeResolve(),commonjs(),],}).then((bundle) => bundle.write({
    file: '.tmp/bundle.js',format: 'umd',sourceMap: 'inline',}));
};

const uglify = () => {
  return src('.tmp/bundle.js',{sourcemaps: true})
      .pipe(plugins.uglify())
      .pipe(dest('.tmp'))
      .pipe(plugins.size({title: 'bundler minified'}));
};

const styles = () => {
  const AutopREFIXER_broWSERS = [
    'ie >= 10','ie_mob >= 10','ff >= 30','chrome >= 34','safari >= 7','opera >= 23','ios >= 7','android >= 4.4','bb >= 10',];

  return src([
    'src/styles/main.scss','src/styles/**/*.css',])
      .pipe(plugins.sassGlob())
      .pipe(plugins.sass({
        precision: 10,}).on('error',plugins.sass.logError))
      .pipe(plugins.autoprefixer(AutopREFIXER_broWSERS))
      .pipe(dest('.tmp'))
      .pipe(plugins.if('*.css',plugins.cssnano()))
      .pipe(dest('.tmp'))
      .pipe(plugins.size({title: 'styles'}));
};

// Uses PUG as template
const templates = (env) => () => {
  return src('./src/templates/*.pug')
      .pipe(plugins.pug({locals: {
        title: pkg.title,description: pkg.description,env,}}))
      .pipe(dest('dist'))
      .pipe(plugins.size({title: 'templates'}));
};

const reload = (done) => {
  server.reload();
  return done();
};


const images = (env) => () => {
  const destination = env === 'deploy' ? 'dist' : '.tmp';

  return src('./src/images/**/*.{gif,jpg,png,svg}')
      .pipe(dest(destination))
      .pipe(plugins.size({title: 'size'}))
};


const serve = () => {
  server.init({
    notify: false,logPrefix: 'WSK',scrollElementMapping: ['main','.mdl-layout'],server: ['.tmp','dist'],port: 3000,});

  watch(
    ['src/**/*.pug'],series(templates('development'),reload)
  );

  watch(
    ['src/styles/**/*.{scss,css}'],series(styles,templates('development'),reload)
  );

  watch(
    ['src/scripts/main.js','src/scripts/**/*.js'],series(bundler,reload)
  );

  watch(
    ['src/images/**/*.{gif,svg}'],series(images('development'),reload)
  );
};

const clean = () => del(['.tmp','dist/*','!dist/.git'],{dot: true});

exports.default = series(
    clean,bundler,uglify,styles,templates('deploy'),images('deploy')
);

exports.serve = series(
    bundler,images('development'),serve
);

据我了解,清理文件后,捆绑器将:

  • 从我的来源htmldistmain.jsdispatchForm.js模板编译后,在scss文件夹中的pug页面中提供服务。

Main.js

import dispatchForm from './modules/dispatchForm';

const domContentLoad = (fn) => {
  if (document.readyState !== 'loading') fn();
  else document.addEventListener('DOMContentLoaded',fn);
};

domContentLoad(() => {
  dispatchForm();
});

dispatchForm.js

const button = document.querySelector('[data-calculator-button]');

function updateValue() {
  const gain  = document.querySelector('[data-calculator-form][name="gain"]:checked');
  const cost  = document.querySelector('[data-calculator-form][name="cost"]:checked');

  if (gain && cost) {
    button.removeAttribute('disabled');
    button.classList.remove('selectors__button--inactive');
  } else {
    button.setAttribute('disabled','');
    button.classList.add('selectors__button--inactive');
  }
}

function dispatchForm() {
  const radioInput = document.querySelectorAll('[data-calculator-form]');
  radioInput.forEach(element => element.addEventListener('input',updateValue));
}

export default dispatchForm;

selectors.pug

...

.selectors__form
    .selectors__radio
      input.selectors__input(type='radio' id='gain-points' name='gain' value='points' data-calculator-form)
      label.selectors__label(for='gain-points')

    .selectors__radio
      input.selectors__input(type='radio' id='gain-money' name='gain' value='money' data-calculator-form)
      label.selectors__label(for='gain-money')

.selectors__form
for value in [70,80,90,100,110,120,130]
  .selectors__radio
    input.selectors__input(type='radio' id=`have-${value}` name='cost' value=value data-calculator-form)
    label.selectors__label(for=`have-${value}`)
      | Até 
      b= ` C$${value}`

button.selectors__button.selectors__button--calculate.selectors__button--inactive(disabled=true data-calculator-button)
...

上面的代码通过selectors.pug的“ bundler”从main.jsdispatchForm.jsgulp中为“成本”或“收益”创建了一些选择器,并将其呈现为html


但是现在我想:

  1. 使用两个按钮提交的值之一(${value}),并将其作为参数传递给将解析JSON file函数

  2. 最后,已解析的JSON结果将传递到另一个pug文件


问题

  1. 如何获取此JSON(从dispatchForm.js?到gulpfile.js?从pug到本地?)并将其传递到另一个pug模板? >

  2. 是否应该在单独的JS模块上处理JSON提取,因为显示的JSON将使用另一个pug模板部分呈现在单独的html页面上?怎么这样?

  3. 是否应在构建时生成所有可能的第二页html文件,并且基于提交的值,JS仅用于显示 个?还是应该将第二个html页面呈现为动态?


gulp-data

我还了解到有gulp-data之类的软件包用于处理json数据,我不知道它们是否是前往此处的方法


此外,此SO question暗示了如何将pug JSON对象传递给客户端JavaScript。

解决方法

您对这个问题的表述方式使我认为您的主要问题是将构建步骤与应用程序“运行时”(例如,当用户使用您的应用程序时)相混淆,就像何时运行dispatchForm.js一样。 Gulp是生成您的项目的工具,但这是要在任何用户与您的网站进行交互之前进行的。

您链接的SO问题是在“运行时”中快速渲染pug页面,从结构上讲,这与在gulp的构建步骤中进行渲染非常不同。

如果我正确地理解了你想要什么,那么我可以通过3种主要方法来做到这一点。第一种方法是让客户端JS操作dom并适当地更改页面。您可以为此使用pug,并通过rollup-plugin-pug(通过此SO answer找到)将其渲染到JS库中。

第二个方法是将其作为对服务器的api调用,然后服务器渲染一个哈巴狗模板(这是您链接的SO问题正在做的事情)。

或者第三,您可以执行一些操作,例如在构建时呈现希望用户访问的所有可能的页面,然后仅使dispatchForm.js将它们发送到适当的页面即可。在这种情况下,我建议在一个地方(例如,一个json文件)定义这些选项,并将其作为gulp管道的源。使gulp从单个文件生成多个文件有点奇怪,但是您可以找到人们进行this github threadthis Stack Overflow answerthis gist等类似操作的各种方式。

编辑

如果您希望事情在“选择提交时”发生,那就是方法1。因此,使用rollup-plugin-pug,它看起来像(完全未经测试并浮出水面):

//- template.pug
.content
  p= gain
  p= cost

// modules/calculateButton.js
import templateFn from '../../templates/partials/template.pug';
 
const button = document.querySelector('[data-calculator-button]');
button.addEventListener('click',(e) => {
   if (e.target.getAttribute('disabled')) return;
   const gain  = document.querySelector('[data-calculator-form][name="gain"]:checked').value;
  const cost  = document.querySelector('[data-calculator-form][name="cost"]:checked').value;
  
  document.getElementById("result").innerHTML = templateFn({
    gain,cost
  });
});

否则,提交时不会解析任何内容。对于第三种方式的示例,我建议您检查一下我上面发送的链接。许多构建脚本只是在寻找您自己的方式来做事情,这些事情具有适当的功能/复杂性,并且易于维护。