代码之家  ›  专栏  ›  技术社区  ›  Justin

我有一些关于Sapper/Svelte的问题

  •  4
  • Justin  · 技术社区  · 7 年前

    我刚开始使用Sapper( https://sapper.svelte.technology )这是第一次。到目前为止,我真的很喜欢。我需要它做的一件事是显示应用程序中可用组件的列表,并显示有关它们的信息。理想情况下,可以基于页面上的动态绑定更改组件的外观。

    关于使用该框架,我有几个问题。

    首先,我将提供一段代码,然后是一个屏幕截图:

    [slug].html
    -----------
    
    <:Head>
    <title>{{info.title}}</title>
    </:Head>
    
    <Layout page="{{slug}}">
        <h1>{{info.title}}</h1>
    
        <div class="content">
             <TopBar :organization_name />
        <br>
        <h3>Attributes</h3>
        {{#each Object.keys(info.attributes) as attribute}}
        <p>{{info.attributes[attribute].description}} <input type="text" on:keyup="updateComponent(this.value)" value="Org Name" /></p>
        {{/each}}
        </div>
    </Layout>
    
    <script>
    import Layout from '../_components/components/Layout.html';
    import TopBar from '../../_components/header/TopBar.html';
    
    let COMPONENTS = require('../_config/components.json');
    
    export default {
        components: {
            Layout, TopBar
        },
    
          methods: {
              updateComponent(value) {
                this.set({organization_name: value});
              }
          },
    
      data() {
          return {
            organization_name: 'Org Name'
          }
      },
    
      preload({ params, query }) {
    
        params['info'] = COMPONENTS.components[params.slug];
    
        return params;
      }
    
    };
    </script>
    

    enter image description here

    现在我的问题是:

    1. 我注意到我不能 #each 通过我的对象。我得把它的钥匙翻个遍。如果我能这样做就好了:

      {{#每个info.attributes作为属性}}

      {{attribute.description}}

      {{/每个}}

    2. 在Sapper之前,我将使用Angular translate模块,该模块可以基于给定的JSON文件对字符串进行翻译。有没有人知道是否存在一个工兵/苗条的等价物,或者这是我可能需要自己想出的东西?

    3. 我不习惯进口。我更习惯于Angular中的依赖注入,它看起来更干净一些(没有路径)。有什么方法可以创建 COMPONENTS 常量,可以在整个文件中使用,还是每次需要访问JSON文件的数据时都需要导入JSON文件?

    4. 作为#3的后续,我想知道是否有一种方法可以更好地包含文件,而不必依赖于使用 ../.. 浏览我的文件夹结构?如果我要更改一个文件的路径,我的终端会抱怨并给出错误,这很好,但我仍然想知道是否有更好的方法来导入我的文件。

    5. 我知道必须有更好的方法来实现我在示例中实现的内容。基本上,您会在属性旁边看到一个输入框,如果我在那里做了更改,我会调用 updateComponent 函数,然后执行 this.set() 在当前范围中重写绑定。这是可行的,但我想知道是否有某种方法可以避免该函数。我想您可以绑定输入的值,并让它自动更新我的 <TopBar> 组件绑定。。。大概

    6. 这个 preload 方法允许我访问 params . 我想知道的是,我是否有办法访问 params.slug 没有预加载功能。

    真正酷的是让一些专家以最好的方式重写我所做的事情,可能会解决我的一些问题。

    1 回复  |  直到 7 年前
        1
  •  8
  •   Rich Harris    7 年前
    1. Svelte只会在类似数组的对象上迭代,因为它不可能保证对象的一致行为,它会抛出各种边缘情况,最好在应用程序级别解决。您可以使用标准JavaScript习惯用法来完成这类工作:
    {{#each Object.values(info.attributes) as attr}}
      <p>{{attr.description}} ...</p>
    {{/each}}
    
    <!-- or, if you need the key as well -->
    {{#each Object.entries(info.attributes) as [key, value]}}
      <p>{{attr.description}} ...</p>
    {{/each}}
    
    1. 不知道直接的角度转换等价物,但一个简单的i18n解决方案是在 preload :
    preload({ params, query }) {
      return fetch(`/i18n/${locale}.json`)
        .then(r => r.json())
        .then(dict => {
          return { dict };
        });
    }
    

    然后,您可以参考以下内容 {{dict["hello"]}} 在模板中。更复杂的解决方案将只加载当前页面所需的字符串,并将缓存所有内容等,但基本思想是一样的。

    1. 我想你可以这样做:
    // app/client.js (assuming Sapper >= 0.7)
    import COMPONENTS from './config/components.json';
    window.COMPONENTS = COMPONENTS;
    
    // app/server.js
    import COMPONENTS from './config/components.json';
    global.COMPONENTS = COMPONENTS;
    

    不过导入并没有那么糟糕!模块的依赖关系最好是明确的。

    1. 您可以使用 resolve.modules 网页包中的字段配置: https://webpack.js.org/configuration/resolve/#resolve-modules

    2. 这将是使用双向绑定的好地方:

    {{#each Object.values(info.attributes) as attr}}
      <p>{{attr.description}} <input bind:value=organization_name /></p>
    {{/each}}
    
    1. 是的 params 对象在页面中始终可用(不是嵌套组件,除非您向下传递道具,而是所有顶级组件,如 routes/whatever/[slug].html )–所以您可以在模板中引用它 {{params.slug}} ,或在生命周期挂钩和方法中 this.get('params').slug ,无论给定组件是否使用 预加载 .