npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sat-router

v1.0.12

Published

Библиотека маршрутизации для Angular

Downloads

21

Readme

SATRouter

Библиотека реализующая собственный механизм маршрутизации, вместо стандартного.

  • [x] Имеет возможность любого уровня вложенности, эта функциональность отсутствует в стандартном Router
  • [x] Работает на основе состояния, представленного в виде обычного массива объектов
  • [x] Состояние может содержит в себе все необходимые для работы приложения
  • [x] Состояние сериализует в адресную строку на основе указанных функций преобразования из/в строку.
  • [x] Состояние можно получать из любого источника
  • [x] Маршруты могут быть динамическими (добавляться/удалятся налету)
  • [x] Поддерживает динамическую загрузку модулей
  • [x] Множество дополнительных вариантов

пример

схема

Исходный код Песочница

Видео

SATRouterModule

Добавляет директивы и сервисы для навигации внутри приложения между представлениями, определенными в приложении. Вы можете импортировать этот NgModule несколько раз, по одному разу, для каждого модуля с отложенной загрузкой.

смотри раздел ISATRouteResolver

@NgModule({
  declarations: [
    //
  ],
  imports: [    
    SATRouterModule.create(
      // Загрузка определённого компонента
      { path: 'root1', component: RootComponent },
      // Динамически загружаемый модуль
      { 
        path: 'root2', 
        loadChildren: () => 
          import('./modules/root2.module').then(_ => _.Root2Module) 
      }
    )
  ],

Указанная регистрация на самом деле регистрирует модуль и провайдер с маршрутами. Вы можете зарегистрировать и по отдельности, например для обеспечения динамических маршрутов

@NgModule({ 
  imports: [    
    SATRouterModule
  ],
  providers: [
    {
      provide: SAT_ROUTE_RESOLVERS, useFactory: (s_files: MainService) =>
      {
        return s_files.files$
          .pipe(
            first(),
            map(fs => [
              { path: '', component: EditorsComponent },
              ...fs.map(f => ({ 
                path: f, 
                component: EditorComponent, 
                alwaysNew: true
                /* так как компонент не меняется, 
                   что бы была анимация указываем флаг alwaysNew */ 
              }))
            ]));

      }, deps: [MainService]
    }
  ]
})

SAT_LINK_PARSE

Токен представляющий функцию преобразования из строки в полное состояние маршрута

providers: [
  {
    provide: SAT_LINK_PARSE,
    useValue: (link: string) =>
    {
      link = /sat-link:([a-z0-9==%_\.\-"]+)/img.exec(link)?.[1] ?? '';

      if (!link) return of<ISATStateNode[]>(
        [0, 1, 2].map(index => ({
          path: 'root1',
          outlet: index.toString(),
          params: { index },
          children: [
            {
              path: 'child1',
              children: [
                { path: 'subChild1', outlet: '0' },
                { path: 'subChild3', outlet: '1' }
              ]
            }
          ]
        }))
      );

      const s = unzip(decodeURIComponent(link));
      return of(JSON.parse(s));
    }
  },

SAT_STATE_STRINGIFY

Токен представляющий функцию преобразования из полного состояния маршрута в строку

providers: [
 {
   provide: SAT_STATE_STRINGIFY,
   useValue: (rs: ISATStateNode[]) =>
   {
     const s = encodeURIComponent(zip(JSON.stringify(rs)));
     return of(`#sat-link:${s}`);
   }
 }

SATRouterService

Сервис для навигации

Перейти по строковой ссылке

navigate('root1/1');

Перейти по состоянию маршрута

navigate([
{
  path: 'root1',
  params: { name: '123' },
  children: [
    {
      path: '1', params: { id: '321' },
      children: [
        { name: 'left', params: { userId: '321' } },
        { name: 'right', params: { userId: '3212' } },
      ]
    }
  ]
},
{
  path: 'root1',
  name: 'rootRight',
  params: ['', 2,],
  children: [
    { name: 'left', params: { admin: true } },
    { name: 'right', params: ['right2', 6] },
  ]
}
])

updateHistoryAsync

Обновление адресной строки браузера

cloneState

Копия маршрута с выделением текущего уровня Служит для модернизации полного маршрута с последующим переходом

const cloned = cloneState(address);
if (!cloned.currentNode) return;
cloned.currentNode.path = newPath;
this.s_router.navigate(cloned.state);

getNode

Получить узел данных маршрута

SATRouterOutletComponent

Контейнер маршрута, который динамически заполняется в зависимости от текущего состояния маршрутизатора.

Каждый контейнер маршрута может иметь уникальное имя, определяемое необязательным атрибутом name.

<sat-router-outlet></sat-router-outlet>
<sat-router-outlet name='left'></sat-router-outlet>
<sat-router-outlet name='right'></sat-router-outlet>

Именованные контейнеры маршрута будут целями маршрута с тем же именем.

Объект ISATStateNode для именованного маршрута имеет свойство outlet для идентификации целевого контейнера маршрута: ts{path: <base-path>, component: <component>, outlet: <target_outlet_name>}

SATRouterLinkActive

Директива для обнаружения активности маршрута

Свойства

Контейнер маршрута

routerOutlet: SATRouterOutletComponent | undefined

Событие активации отслеживаемого маршрута

isActive$: BehaviorSubject<boolean>

Событие активации отслеживаемого маршрута

activated: EventEmitter<string>

Пример использования

<nav mat-tab-nav-bar>
  <a mat-tab-link (click)="onTabClick()" 
     [satRouterLinkActive]="{rout_path}"
     [routerOutlet]="outlet"
     #rl="satRouterLinkActive"
     [active]="rl.isActive$ | async">
    {{tab1_header}}
  </a>

</nav>
<sat-router-outlet #outlet ></sat-router-outlet>

Защитники

canActivate

Проводит проверку можно ли перейти к маршруту

Представлен в виде свойства распознавателя маршрута ISATRouteResolver canActivate и интерфейсом ISATCanActivate может принимать одиночный объект SATCanActivate или массив SATCanActivate[]

canDeactivate

Проводит проверку можно ли покинуть маршрут Представлен в виде свойства распознавателя маршрута ISATRouteResolver canDeactivate и интерфейсом ISATCanDeActivate может принимать одиночный объект SATCanDeActivate или массив SATCanDeActivate[]

Отладка

Предусмотрен режим отладки с показом SATRouterOutletComponent и текущем состоянием маршрута для этого необходимо зарегистрировать провайдер

{ provide: SAT_ROUTE_CONFIGURATION, useValue: { debug: true } }

пример демо режима

Типы

ISATStateNode

interface ISATStateNode
{
  /** Путь маршрута */
  path?: string;
  /** Имя контейнера маршрута */
  outlet?: string;
  /** Дочерние маршруты */
  children?: ISATStateNode[];
  /** Параметры маршрута*/
  params?: any;
}
ts
### ISATRouteResolver
Интерфейс распознавателя части маршрута
```ts
interface ISATRouteResolver
{
  /** Путь маршрута, если есть именованные контейнеры,
   * то они пишутся `{путь}:{outlet}`
   */
  path: string;
  /** Тип компонента */
  component?: Type<any>;
  /** Загрузчик динамического модуля */
  loadChildren?: LoadChildrenCallback;
  /** Перенаправление */
  redirectTo?: string;
  /** Можно ли активировать */
  canActivate?: ISATCanActivate | ISATCanActivate[];
  /** Можно ли деактивировать */
  canDeactivate?: ISATCanDeActivate | ISATCanDeActivate[];
  /** Можно ли выгружать */
  canUnload?: boolean;
  /** Не проверять на изменение компонента */
  alwaysNew?: boolean;
}

ISATCanActivate

Интерфейс имеет одну функцию, функция может быть асинхронной

interface ISATCanActivate
{
  canActivate(state: RoutePath): 
  Observable<boolean> | Promise<boolean> | boolean;
}

Пример:

SATRouterModule.create([
  { path: '', component: Child1Component },  
  { path: 'subChild3:1', component: Child1Sub1Component },
  {
    path: 'subChild4:1', component: Child1Sub2Component,
    canActivate:
    {
      // тут пример асинхронной проверки реализованной через Promise
      canActivate: async (state: RoutePath) =>
      {
        alert(`нельзя перейти в маршрут "subChild4:1"`)
        return false;
      }
    },
    // при неудачной проверке на активацию перейти на маршрут
    redirectTo: 'subChild3:1'
  }
])

ISATCanDeActivate

интерфейс имеет одну функцию, функция может быть асинхронной

interface ISATCanDeActivate
{
  canDeActivate(component: any, state: RoutePath): 
    Observable<boolean> | Promise<boolean> | boolean;
}

пример

SATRouterModule.create([
  { path: '', component: Child1Component },  
  {
    path: 'subChild2:0', component: Child1Sub2Component,
    canDeactivate: {
      // тут пример асинхронной проверки реализованной через Promise
      canDeActivate: async (component: any, state: RoutePath) =>
      {
        alert('нельзя покинуть маршрут "subChild2:0"')
        return false;
      }
    }
  }
])