如何从 index.html 获取值并在解析 JSON 文件后使用它来呈现第二个模板?

How can I get a value from index.html and use it to render a second template after parsing JSON file?

我正在努力思考 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, templates('development'), reload)
  );

  watch(
    ['src/images/**/*.{gif,jpg,png,svg}'],
    series(images('development'), templates('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,
    styles,
    templates('development'),
    images('development'),
    serve
);

据我了解,清理文件后,打包器将:


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)
...

上面通过 gulps [=] 从 selectors.pugmain.jsdispatchForm.js 为 'cost' 或 'gain' 创建了一些选择器129=],并将其呈现为 html.


但现在我想:

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

    的函数
  2. 最后,解析的JSON结果会被传递给另一个pug文件


问题

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

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

  3. 是否应该在构建时生成所有可能的第二页 html 文件,并根据提交的值使用 JS 仅显示 一个?或者应该动态呈现第二个 html 页面?


gulp-数据

我也了解到有像gulp-data这样的包,用来处理json数据,不知道是不是这里的路


此外,此 提示如何将 pug JSON 对象传递到客户端 JavaScript。

你表达这个问题的方式让我认为你的主要问题是将构建步骤与应用程序“运行时间”(例如,当用户使用你的应用程序时)混为一谈,比如 dispatchForm.js 将永远是 运行。 Gulp 是一种用于生成项目的工具,但这意味着在任何用户与您的网站交互之前发生。

您链接的 SO 问题是在“运行 时间”快速呈现哈巴狗页面,从架构上讲,这与 gulp 在构建步骤中发生的情况有很大不同。

如果我能正确理解您的需求,那么在我的脑海中有 3 种主要方法可以做到。第一种是让 client-side JS 操纵 dom 并适当地更改页面。你可以为此使用 pug,通过 rollup-plugin-pug (found via this ).

之类的东西呈现到 JS 库中

第二个是 api 调用服务器,然后呈现哈巴狗模板(这就是您链接的 SO 问题所做的)。

或者第三,您可以做一些事情,比如在构建时呈现您希望用户访问的所有可能页面,然后让 dispatchForm.js 将它们发送到适当的页面。在这种情况下,我建议在一个地方(比如 json 文件)定义这些选项,并将其作为 gulp 管道的源。 gulp 从单个文件生成多个文件有点滑稽,但你可以找到人们做类似事情的各种方式,如 this github thread, , this 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
  });
});

否则提交时不会解析任何内容。对于第三种方式的示例,我建议查看我上面发送的链接。很多构建脚本只是找到自己的方式来做一些事情,这些事情具有适当的 power/complexity 与易于维护的平衡。