文档章节

用koc-loader写类Vue的Knockout单文件组件

Zaaksam
 Zaaksam
发布于 2017/11/16 17:16
字数 850
阅读 240
收藏 3

前言

在前端界MVVM框架高速发展中,各种工具链的完善和普及,作为MVVM鼻祖的Knockout(下称ko)在这波浪潮中却掉队了。其中,以国内优秀MVVM框架Vue为例,带来了单文件组件的新一波666操作,写起组件来爽快感爆棚。而受限于万恶的IE浏览器问题,我们并不能使用Vue来打造一切。那么,有没有办法像Vue单文件组件一样来写ko的组件呢?找了一圈,没有。本着开源分享精神,在基于vue-loader和san-loader的基础上,进行一些小改,撸了一个koc-loader,实现了类似Vue单文件组件的开发形式。

安装

yarn add koc-loader css-loader style-loader html-loader -D

配置

因个人喜爱偏好,下述内容都是基于Typescript的代码演示。理论上支持script使用js、babel、coffeescript等loader组合

webpack.config.js

使用了ts-loader,请注意 entry 入口必须是 .ts 文件

{
    resolve: {
        extensions: ['.ts', '.js', '.koc']
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                test: /\.ts$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
                options: {
                    appendTsSuffixTo: [/\.koc$/]
                }
            },
            {
                test: /\.koc$/,
                loader: 'koc-loader'
            }
        ]
}

koc.d.ts

需要定义 .koc 文件的声明

/// <reference types="knockout" />
 
declare module "*.koc" {
    const koc: KnockoutComponentTypes.Config
    export default koc
}

示例代码

<template>
    <div>
        <div data-bind="text: info"></div>
        <menu></menu>
    </div>
</template>

<script lang="ts">
import ko from 'knockout';
import Menu from "./src/component/menu/menu.koc"; //加载其他ko组件

ko.components.register('menu', Menu);

export default class viewModel {
  info: KnockoutObservable<string>;

  constructor(params: any) {
    this.info = ko.observable("hello koc-loader");
  }
}
</script>

是不是很Vue?

koc工作机制

通过ko的d.ts文件定义,我们可以得知 ko.components.register 的方法定义:

register(componentName: string, config: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig): void;

其中 KnockoutComponentTypes.Config 定义为:

interface Config {
        viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
        template: string | Node[]| DocumentFragment | TemplateElement | AMDModule;
        synchronous?: boolean;
    }

example.koc 的示例代码中的script导出的实际上是 ViewModelFunction ,怎么能直接丢给 register 呢?

实际上,这里就是 koc-loader 的中间作用了,它会将script中导出的 viewModel 进行一个代码封装:

var Component = {
    viewModel: function (params) {
        return new __koc_script__(params)
    },
    template: __koc_template__
}
module.exports = Component

最终script部份导出的,就是一个符合 KnockoutComponentTypes.Config 定义的对象,perfect~~

注:params参数,请参照ko官网文档

进阶

使用index.ts实现默认导出

可以在 .koc 文件同名目录下,建立 index.ts 文件

import Menu from './menu.koc'
export default Menu

这样我们导入组件时,可以使用下面的更简短的方式:

import Menu from './src/component/menu'

ko.components.register('menu', Menu)

更简洁的组件注册

通过上面的代码我们看到用 ko.components.register 比较罗嗦,这时Vue的组件注册形式又浮现出来,我们又马上撸了一个类似的形式:

kocHelper.ts

import ko from 'knockout'
import _ from 'lodash'

interface Components {
    [key: string]: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig
}

export function Use(components: Components) {
    for (let c in components) {
        let name = _.kebabCase(c) //ko组件名称需要符合kebab-case

        if (ko.components.isRegistered(name)) {
            //同名组件已存在,跳过
            continue
        }

        ko.components.register(name, components[c])
    }
}

OK,现在我们就可以这么注册组件了:

import kocHelper from './kocHelper'
import IMenu from './src/component/menu'
let IMenu2 = IMenu
let IMenu3 = IMenu

kocHelper.Use({
    IMenu,
    IMenu2,
    IMenu3
})

结尾

ko最大的问题就是太老了,资源匮乏,但是因为众所周知的原因,我们还需要它,当然,今天我们可能有另一些新的选择,比如百度的san,但在我们离开之前,我们希望能让ko的开发更加有趣一些,这样也就满足了。

相关资源:

© 著作权归作者所有

Zaaksam
粉丝 3
博文 2
码字总数 1915
作品 2
深圳
其他
私信 提问
加载中

评论(1)

试试帆布鞋
试试帆布鞋
👍
用于 webpack 的 Knockout 组件加载器--koc-loader

koc-loader 是一个 webpack loader,可以使用类似 Vue 单文件组件的风格来编写和使用 Knockout 组件。 代码上基于 vue-loader、san-loader 进行编写,支持各种其他 loader 组件的搭配使用。 ...

Zaaksam
2017/11/19
340
0
WijmoJS V2019.0 Update2 发布:增强 React 和 Vue 组件功能

前端开发工具包 WijmoJS 在2019年的第二个主要版本 V2019.0 Update2 已经发布,本次发布涵盖了React 和 Vue 框架下 WijmoJS 前端组件的功能增强,并加入更为易用且灵活的撤消/重做功能和模板...

葡萄城技术团队
09/19
364
0
从vue-loader源码分析CSS Scoped的实现

本文同步在个人博客shymean.com上,欢迎关注 虽然写了很长一段时间的Vue了,对于的原理也大致了解,但一直未曾关注过其实现细节。最近在重新学习webpack,因此查看了源码,顺便从的源码中整理...

橙红年代
09/21
0
0
[译] Vue.js  —  注意事项和技巧

原文地址:Vue.js — Considerations and Tricks 原文作者:Harshal Patil 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:xingqiwu55555 校对者:jerryOnlyZRJ Vu...

星期五
02/07
0
0
从零开始构建一个vue项目 --- webpack历险记

本文分上、中、下三个部分(先写上篇) webpack历险记之一个简单的vue hellowrld (上) vue项目搭建之vue全家桶和element ui、规范、单元测试等等。。。(中) vue项目优化之打包优化,页面加载优...

awsky
04/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
14
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
15
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部