# Vue.js 和 Webpack
使得 Pagekit 吸引开发者的一个重要的方面就是,Pagekit 的界面是用 Vue.js 框架构建的。
在浏览例子时,你可能会困惑于Vue.js、Webpack、javascript 模块以及用于起步的一般文件结构的理念。本文旨在为你厘清这些东西。
## 术语
**Vue.js** 是一个创建交互式 web 界面的 javascript 框架。它负责将 javascript 对象(model)和呈现的模板(view)二者同步。在 Vue.js 文档中可以找到详尽的介绍文章。阅读此框架的[起步指南](http://vuejs.org/guide/) 和更多的[高级概念](http://blog.evanyou.me/2015/10/25/vuejs-re-introduction/) 。
**Vue 组件** 是代码的逻辑实体,它包含定义良好的功能,并且通常包括一个视图模板+一个用来定义组件内部交互的脚本。在 Pagekit 中,可以添加到系统的许多实体都是以 Vue 组件的形式创建并注册到 Pagekit 系统的。包括小工具、仪表盘小工具和链接类型等。在代码级上,它们都在 `*.vue` 文件中结合了 javascript 代码和 HTML 模板。可以使用 Webpack 将 `*.vue` 文件编译成为纯`*.js`文件。你还可以在 `*.js` 文件中创建 Vue 组件,组件使用的模板在不同的文件定义,或者只是一个简单的字符串,这种情况下就不必使用 Webpack了。
**Webpack** 是一款模块打包工具,它会获取你的开发资源(比如 Vue 组件和原生 javascript 文件)并将它们结合到所谓的包(bundle)。这不同于简单地链接和压缩 javascript文件。简言之,在当前页面被加载时模块才会用到相关的 webpack 包(with webpack bundles only the modules required on the current page are loaded)。了解更多,查阅[Webpack 背后的动机](http://webpack.github.io/docs/motivation.html)。
**Note** 一个常见的误解是,在开发 Pagekit 扩展时必须使用 Webpack。并非如此。如果简单地创建和引入单个 javascript 文件对你来说更容易起步。你可以选择稍后在迁移到 Webpack.
## 不使用 Webpack 时的文件结构
如果你打算在没有 Webpack 的情况下使用 Vue.js,这里有一个例子 [todo extension](https://github.com/pagekit/example-todo).
1. 创建 JavaScript 文件, i.e. `js/todo.js`.
2. 在模板中加载 JavaScript 文件。确保 `vue` 在你的脚本之前加载。`<?php $view->script('todo', 'todo:js/todo.js', 'vue') ?>`
## 为何使用 Webpack ?
没有 Webpack,位于名为 `example.js` 文件中的关于一个简单的 Vue 组件的例子大概是这样:
```
new Vue({
el: '<div>{{ message }}</div>',
data: {
message: 'Hello Pagekit!'
}
})
```
如果你不喜欢使用 Webpack,这个解决方案非常好。使用 Webpack 来编译 `*.vue` 模板可以为你的文件形成更好的组织结构。可以在 `example.vue` 文件中以可读的方式定义标签和 javascript 代码。
```
<template>
<div>
{{ message }}
</div>
</template>
<script>
module.exports = {
data: {
message: 'Hello Pagekit!'
}
}
</script>
```
如你所见,不必再用笨拙的字符串来定义模板了。Webpack 将可读的 `*.vue` 转换并编译成为 `*.js` 文件,模板标签则转换成为行内字符串。
Webpack 是在终端运行的工具,可以将 `*.vue` 文件编译成为 `*.js` 文件。Pagekit 的根目录有一个默认的 `webpack.config.js`。在 Pagekit 根目录运行 `webpack` 或 `webpack --watch`,它会在 `packages` 子目录中遍历所有主题和扩展。
你的包(package)还需要它自己的 `webpack.config.js`,例如 `packages/pagekit/example/webpack.config.js`。此文件定义哪些 `*.vue` 文件应当被编译成什么输出文件。
下面的例子假设你的 `*.vue` 文件位于 `packages/pagekit/example/app/components` 包的子目录,并且它们应当在编译后输出到 `packages/pagekit/example/app/bundle`目录。
```
module.exports = [
{
entry: {
"example" : "./app/components/example.vue",
"example-2": "./app/components/example-2.vue",
"example-3": "./app/components/example-3.vue"
},
output: {
filename: "./app/bundle/[name].js"
},
module: {
loaders: [
{ test: /\.vue$/, loader: "vue" }
]
}
}
];
```
现在打开终端,前往 Pagekit 根目录并运行 `webpack` 或 `webpack --watch` 使用你刚刚添加的配置来运行 Webpack。你会在包的 `app/bundle` 目录中看到 `*.js` 文件。例如 `example.vue` 会被编译成名为`example.js` 的包(bundle)文件。
**Note** 在使用 Git 管理代码时,建议添加 `app/bundle` 目录到 `.gitignore` 文件中,因为它只包含 `*.vue` 组件被编译后的版本。
要加载和使用已编译的 Vue 组件,从视图模板中加载已编译的包文件,例如来自 `views/example.php` 的文件。你还需要将 `vue` 作为第三个参数,这样你的组件只会在 Vue 本身的脚本文件被加载后再进行加载。
```
<?php $view->script('example', 'hello:app/bundle/example', 'vue') ?>
```
## 摘要:Webpack 下的文件结构
对于包含 webpack 配置文件的设置,查看 [hello extension](https://github.com/pagekit/extension-hello)。
1. 在你的扩展中创建 Vue 组件。例如 `*.vue` 文件: [link.vue](https://github.com/pagekit/extension-hello/blob/master/app/components/link.vue).
2. 为你的扩展程序创建 `webpack.config.js`。Webpack 配置定义了你的扩展提供的哪些 javascript 模块应当被编译成为什么样的最终文件。一个例子: [webpack.config.js](https://github.com/pagekit/extension-hello/blob/master/webpack.config.js)
3. 在 Pagekit 的根目录中运行 `webpack` 或 `webpack --watch`。Pagekit 的 webpack 会遍历所有的包,并读取它们的 webpack 配置。
4. 在视图文件中引入生成的包 `<?php $view->script('settings', 'hello:app/bundle/settings.js', ['vue', 'jquery']) ?>`
## 创建和注册 Vue 组件
使用目前的文件结构设置,你现在可以创建自己的脚本和 Vue 组件。默认情况下,上面提到资源都包含在你自己的视图文件中。然而在某些情况下,你创建了一个 Vue 组件,并希望将它注册到 Pagekit 系统,使之可以显示在 Pagekit 管理界面的相应位置。你可以如此处理以下这些元素:
* 仪表盘小工具
* 网站小工具
* 链接类型
* 站点树设置,在编辑单个页面时以选项卡的形式显示
* 针对扩展设置的模态弹出
这基本上发生在四个步骤:
1. 编写一个 Vue 组件,i.e. `app/components/link.vue`. [Source example](https://github.com/pagekit/extension-hello/blob/master/app/components/link.vue)
2. 通过 javascript 注册这个 Vue 组件, i.e. `window.Links.components['hello'] = module.exports;`. [Source example](https://github.com/pagekit/extension-hello/blob/master/app/components/link.vue#L39)
3. 将这个 Vue 组件添加到 webpack 包中,i.e. `"link": "./app/components/link.vue"`. [Source example](https://github.com/pagekit/extension-hello/blob/master/webpack.config.js#L6)
4. 确保组件的包文件在后台已经通过 PHP 被加载了, i.e. `$scripts->register('hello-link', 'hello:app/bundle/link.js', '~panel-link');` [Source example](https://github.com/pagekit/extension-hello/blob/master/index.php)
**Note** 这些就是使用 Webpack 的必要步骤。没有 Webpack 同样也能实现。只需跳过第三步。你可以在一个原生的 `*.js` 文件中创建 Vue 组件以及以文本字符串作为 `template`属性的值的模板。记得在第四步使用该 javascript 文件的路径。