Svelte系列 --- 特殊元素

1,462 阅读1分钟

Svelte 提供了各种内置的特殊元素。这些特殊元素必须被设置为顶层元素

svelte:self

表示当前组件,允许在某些情况递归自身,这对于展示文件夹树之类的视图很有用,其中文件夹可以包含 其他 文件夹

基于 <svelte:self> 的作用是引用自身组件的构造函数,因此它十分容易导致堆栈溢出

所以,<svelte:self> 必须包裹在 #if 块或者 #each 块中,或者由插槽传给组件,其余情况均是禁止的

父组件

<script>
  import Folder from './Folder.svelte';

  let folders = [
    {	
      name: '音乐',
      folders: [
        { name: '流行音乐' },
        { name: '纯音乐' },
        { name: '吉他' }
      ]
    },
    {
      name: '电影',
      folders: [
        {
          name: '喜剧片', 
          folders: [
            { name: '周星驰' },
            { name: '黄渤' },
            { name: '沈腾' }
          ]
        },
        {
          name: '动作片',
          folders: [ { name: '李连杰' } ]
        }
      ]
    }
  ];
</script>

<Folder name="根目录" {folders} />

子组件 --- Folder

<script>
  export let name = 'noname';
  export let folders = []
</script>

<style>
  ul { padding: 0.2em 0 0 1.5em; margin: 0 0 0 0.5em; list-style: none; }
  li { padding: 0.2em 0; }
</style>

<span>- {name}</span>

<ul>
  {#each folders as folder}
    <li>
      <!--
	不可以在 Folder.svelte 中直接使用 <Folder> 自身,因为模块不能导入自身
	所以我们需要使用svelte:self组件
      -->
      <svelte:self {...folder}/>
    </li>
  {/each}
</ul>

svelte:component

根据属性值渲染不同的组件,类似于vue的<component />

<script>
  import Red from './Red.svelte';
  import Green from './Green.svelte';
  import Blue from './Blue.svelte';

  let selected = '0';
  $: component = [Red, Green, Blue][selected]
</script>

<select bind:value={selected}>
  <option value="0"></option>
  <option value="1">绿</option>
  <option value="2"></option>
</select>

<!-- this的值可以是任何组件的构造函数,如果提供的是一个假值,则不会渲染这个组件。 -->
<svelte:component this={component} />

svelte:window

可以通过<svelte:window>来监听window对象的事件,例如鼠标移动的事件

也可以在<svelte:window>上添加像 preventDefault 这样的 事件修饰符,这与 DOM 元素的方法并无二致

<script>
  let x, y
</script>

<svelte:window on:mousemove={ e => ({x, y} = e) } />

<p>鼠标位置:{x}, {y}</p>

还可以绑定一些window的属性,某些业务我们可能需要监测浏览器窗口的大小,原生的写法是通过监听 window.onresize 来实现的

<script>
  let width, height
</script>

<svelte:window bind:innerWidth={width} bind:innerHeight={height} />

<p>Window Size: width={width}, height={height}</p>

支持绑定的属性列表如下:

属性名描述备注
innerWidth获得浏览器窗口的内容区域的宽度,包含垂直滚动条(如果有的话)只读
innerHeight获得浏览器窗口的内容区域的高度,包含水平滚动条(如果有的话)只读
outerWidth获得浏览器窗口的宽度只读
outerHeight获得浏览器窗口的宽度只读
scrollXdocument 在水平方向已滚动的像素值可以修改
scrollYdocument 在垂直方向已滚动的像素值可以修改
onlinewindow.navigator.onLine 的别名,代表当浏览器能够访问网络只读

svelte:body

<svelte:window>类似,<svelte:body>元素允许你监听document.body上的事件。这对于mouseentermouseleave事件来说十分有用,它们无法在window上触发。

<script>
  let msg = ''
</script>

<svelte:body
  on:mouseenter={() => msg = 'Enter'}
  on:mouseleave={() => msg = 'Leave'}
/>

<div>{msg}</div>

svelte:head

<svelte:head>元素允许你将其他元素插入到文档中的<head>

<head> 中可以插入例如 <script><link><title><meta> 等等元素

在服务器端渲染 (SSR) 模式下,<svelte:head> 的内容与 HTML 的其余部分是分别返回的。

<svelte:head>
  <title>svelte:head</title>
  <link rel="stylesheet" href="./global.css">
  <meta name="key" content="keys">
  <meta name="description" content="description">
</svelte:head>

svelte:fragment

在某些情况下,我们不得不借助一些别的元素来进行模板的编写

但是这样可能会影响到组件原有的布局或者会多出一些不必要的元素标签

<!-- 
  为了设置插槽默认值,我们不得不使用一个div将默认内容包裹起来
  在实际渲染中,外层的这个div其实是没有任何实际意义的
  如果设置样式的时候,可能因为这个多余的div的存在而对样式设置产生对应的影响
-->
<div slot="address">
  <span>name: Steven</span>
  <span>address: Wallaby Way Sydney</span>
</div>
<!-- 
  svelte:fragment和react的fragment标签类似
  在实际渲染的时候,会被自动去除
-->
<svelte:fragment slot="address">
  <span>name: Steven</span>
  <span>address: Wallaby Way Sydney</span>
</svelte:fragment>

svelte:options

<svelte:options>允许你配置编辑器(Svelte)在编译当前组件为原生JavaScript类的时候的一些编译配置项

在99.9% 的情况下,你无需手工干预编译器的默认选项,除非你有十分明确的理由。

App.svelte

<script>
  export let x = 'hello'
</script>

<!-- accessors就是一个编辑器配置项 -->
<svelte:options accessors />

<p>{x}</p>
// 没有添加accessors的时候,App.svelte会被编译为如下JS类
class App extends SvelteComponent {
  constructor(options) {
    super();
    init(this, options, instance, create_fragment, safe_not_equal, { x: 0 });
  }
}

export default App;
// 添加了accessors的时候,App.svelte会被编译为如下JS类
class App extends SvelteComponent {
  constructor(options) {
    super();
    init(this, options, instance, create_fragment, safe_not_equal, { x: 0 });
  }

  // 即给props设置了set和get方法
  get x() {
    return this.$$.ctx[0];
  }

  set x(x) {
    this.$set({ x });
    flush();
  }
}

export default App;
可配置选项功能默认值
immutable是否会使用会使用可变数据
如果确定不会使用可变数据, svelte在编译的时候,
会执行简单的引用相等性检查来确定值是否已更改
false
accessors是否为组件的 props 添加 getter 和 setter方法false
namespace将使用此组件的命名空间
tag将组件编译为自定义元素时,指定的标签名称