---
# System prepended metadata

title: ThinkPHP 5.1 結合 VUE

---

# ThinkPHP 5.1 結合 VUE


## 配置ThinkPHP

### 安裝"驗證碼"
```
composer require topthink/think-captcha 2.0.*
```
### 安裝"數據遷移"
```
composer require topthink/think-migration 2.0.*
```
### 安装"Blade"
```
composer require luoyy/think-blade 3.0.*
```
#### 配置/config/template.php
```
// 模板引擎类型
'type' => 'Blade',
// 视图基础目录(集中式)
'view_base' => Env::get('ROOT_PATH') . 'resources' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR,
// 模板起始路径
'view_path' => Env::get('ROOT_PATH') . 'resources' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR,
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板文件后缀
'view_suffix' => 'blade.php',
'cache' => [
    'cache_subdir' => false,
    'prefix' => '',
],
'tpl_replace_string' => [],
```


## 安裝Webpack
```
npm i -D @babel/core @babel/plugin-transform-runtime @babel/preset-env babel-loader babel-plugin-transform-regenerator babel-polyfill clean-webpack-plugin css-loader file-loader mini-css-extract-plugin node-sass sass-loader style-loader url-loader vue-loader vue-template-compiler webpack webpack-cli
```

### 添加相關依賴
```
npm i -S @fortawesome/fontawesome-free axios bootstrap bootstrap-vue crypto-js element-ui jquery lodash swiper vee-validate vue
```

### 配置Webpack

```
const webpack = require('webpack')
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  entry  : './resources/app.js',
  output : {
    path    : path.resolve(__dirname, 'public/static'),
    filename: 'app.js',
  },
  resolve: {
    alias: {
      'vue': 'vue/dist/vue.js',
    },
  },
  module : {
    rules: [
      {
        test   : /\.(js)$/,
        exclude: /(node_modules)/,
        use    : {
          loader : 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
      {
        test  : /\.(vue)$/,
        loader: 'vue-loader',
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/,
        use : {
          loader : 'url-loader',
          options: {
            limit     : 1000, //bytes
            name      : '[hash:7].[ext]',
            outputPath: 'assets',
          },
        },
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use : [
          {
            loader : MiniCssExtractPlugin.loader,
            options: {
              publicPath: './',
            },
          },
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename     : 'app.css',
      chunkFilename: 'app.css',
    }),
    new CleanWebpackPlugin(),
    new VueLoaderPlugin(),
  ],
}
```
## 配置Vue

### 配置 resources/app.js

```
import 'babel-polyfill'
import Vue       from 'vue'
import './plugin/vee-validate.js'
import './plugin/bootstrap-vue.js'
import './plugin/element-ui.js'
import './scss/app.scss'
import axios     from './plugin/axios.js'

Vue.prototype.$http = axios

new Vue({
  el: '#app',
})

```

### 添加樣式Bootstrap
路徑:resources/plugin/bootstrap-vue.js
```
import Vue                                 from 'vue'
import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue'

const config = {
  'BButton': {
    'variant': 'primary',
  },
}
Vue.use(BootstrapVue, config)
Vue.use(BootstrapVueIcons)

```

### 添加樣式Element-UI
路徑:resources/plugin/element-ui.js
```
import Vue                                 from 'vue'
import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue'

const config = {
  'BButton': {
    'variant': 'primary',
  },
}
Vue.use(BootstrapVue, config)
Vue.use(BootstrapVueIcons)

```

### 添加樣式Axios
路徑:resources/plugin/axios.js
```
import axios       from 'axios'
import { Message } from 'element-ui'

axios.defaults.baseURL = '/api'
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
axios.interceptors.response.use(response => {
  if (response.data.code) {
    Message({
      type   : 'error',
      message: response.data.message,
    })
  }
  return response.data
}, error => {
  Message({
    type   : 'error',
    message: error.response.data.message ?? error.message,
  })
})

export default axios
```

### 添加樣式Vee-Validate
路徑:resources/plugin/vee-validate.js
```
import Vue                                                          from 'vue'
import { ValidationObserver, ValidationProvider, extend, localize } from 'vee-validate'
import * as rules                                                   from 'vee-validate/dist/rules'
import TW                                                           from 'vee-validate/dist/locale/zh_TW.json'

Object.keys(rules).forEach((rule) => {
  extend(rule, rules[rule])
})

localize('zh_TW', TW)

Vue.component('ValidationObserver', ValidationObserver)
Vue.component('ValidationProvider', ValidationProvider)
```

### 添加樣式App.scss
路徑:resources/scss/app.scss
```
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap');
@import "~element-ui/lib/theme-chalk/index.css";
@import "~@fortawesome/fontawesome-free/css/all.min.css";
* {
  font-family: 'Noto Sans TC', sans-serif;
}
```