Laravel+Vuetify 前后端分离项目中 Vue.js 的初始化

Vue.js 初始化

安装相关

webpack.mix.js

解决浏览器缓存问题,追加 .version() 方法;

const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css').version()

安装 Vue 2、 Vuetify 和相关字体图标

npm  install vue
npm  install --save vuetify
npm  install material-design-icons-iconfont -D
npm  install @mdi/font -D

移除 Bootstrap

npm remove bootstrap
npm remove bootstrap-sass

接下来打开 resources/assets/js/app.js 移除对 resources/assets/js/bootstrap.js 文件的引用。

require('./bootstrap');

安装 Vue Router 和 Vuex

npm install vue-router --save-dev
npm install vuex --save-dev

初始化文件

touch resources/js/config.js \
resources/js/event-bus.js \
resources/js/routes.js \
resources/js/store.js \
resources/js/config.js

配置文件
resources/js/config.js

/**
 * Defines the API route we are using.
 */
var api_url = '';
var app_url = '';
switch( process.env.NODE_ENV ){
    
    
    case 'development':
        api_url = 'http://www.hypercell.com/api/v1';
        app_url = 'http://www.hypercell.com';
        break;
    case 'production':
        api_url = 'http://www.hypercell.com/api/v1';
        app_url = 'http://www.hypercell.com';
        break;
}

export const SUPCELL_CONFIG = {
    
    
    API_URL: api_url,
    APP_URL: app_url,
};

事件总线文件

resources/js/event-bus.js

import Vue from 'vue';
export const EventBus = new Vue();
resources/js/routes.js 路由文件

/*
 |-------------------------------------------------------------------------------
 | routes.js
 |-------------------------------------------------------------------------------
 | Contains all of the routes for the application
 */

/**
 * Imports Vue and VueRouter to extend with the routes.
 */
import Vue from 'vue'
import VueRouter from 'vue-router'

/**
 * Extends Vue to use Vue Router
 */
Vue.use( VueRouter )

/**
 * Makes a new VueRouter that we will use to run all of the routes for the app.
 */
import store from './store.js';

export default new VueRouter({
    
    

    routes: [
        {
    
    
            path: '/',
            name: 'Layout',
            components: Vue.component( 'Layout', require( './pages/Layout' ) ),
        },
    ]
});

Vuex 模块的起点文件
resources/js/store.js

/*
 |-------------------------------------------------------------------------------
 | VUEX store.js
 |-------------------------------------------------------------------------------
 | Builds the data store from all of the modules for the Supcell app.
 */

/**
 * Adds the promise polyfill for IE 11
 */
require('es6-promise').polyfill();

/**
 * Import Vue and Vuex
 */
import Vue from 'vue'
import Vuex from 'vuex'

/**
 * Initializes Vuex on Vue.
 */
Vue.use( Vuex );

/**
 * Export our data store.
 */
export default new Vuex.Store({
    
    
    modules: {
    
    
       
    }
});

初始化目录

mkdir -p resources/js/api \
resources/js/components \
resources/js/mixins \
resources/js/pages \
resources/js/modules \
resources/js/plugins \
resources/js/common/lang
  • resources/js/api 目录,用于存放前端 API 供路由调用

  • resources/js/components 目录,用于存放 Vue 组件

  • resources/js/mixins 目录,用于存放 mixins

  • resources/js/pages 目录,用来存放页面

  • resources/js/modules 目录,用于数据存储,Vuex 将数据分割到多个组件并存放到这个目录。

  • resources/js/plugins 目录,用于存放自定义的插件。

  • resources/js/common/lang 目录,用于存放语言包。

i18n 国际化

npm install vue-i18n

新建插件目录

mkdir -p resources/js/plugins/

新建 vue-i18n 插件

touch resources/js/plugins/vue-i18n.js

编辑 vue-i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n);
//定义标识符
const i18n = new VueI18n({
    
    
    locale: 'zh-CN',    // 语言标识
    //this.$i18n.locale // 通过切换locale的值来实现语言切换
    messages: {
    
    
        'zh-CN': require('../common/lang/cn'),   // 中文语言包
        'en': require('../common/lang/en')    // 英文语言包
    }
});
export  {
    
    i18n}

新建语言包目录

mkdir -p resources/js/common/lang
touch resources/js/common/lang/en.js
touch resources/js/common/lang/cn.js

编辑语言包
resources/js/common/lang/cn.js

export const m ={
    
    
    hello: '你好'
};
// resources/js/common/lang/en.js
export const m ={
    
    
    hello: 'hello'
};

配置 app.js

window._ = require('lodash');
// try {
    
    
//     window.$ = window.jQuery = require('jquery');
// } catch (e) {}
/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.
 */
// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
    config => {
    
    
        if (localStorage.getItem('Authorization')) {
    
    
            config.headers.Authorization = localStorage.getItem('Authorization');
        }
        return config;
    },
    error => {
    
    
        return Promise.reject(error);
    });
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    
    
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    
    
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
import Vue from 'vue';
import router from './routes.js'
import store from './store.js'
// 引入vuetify
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import '@mdi/font/css/materialdesignicons.css'
import  {
    
    i18n} from  './plugins/vue-i18n'

Vue.use(Vuetify);


new Vue({
    
    
    //定义Vue绑定的根元素
    el: '#app',
    //将上面声明的路由器传递到根Vue实例
    router,
    store,
    i18n,
    //初始化Vuetify
    vuetify: new Vuetify()
}).$mount('#app'); //将这个实例挂载到id=app的根元素上

编辑父模板 Layout.vue,其他模板继承此模板

touch resources/js/pages/Layout.vue
<template>
    <v-app id="inspire">
        <v-navigation-drawer
                v-model="drawer"
                :clipped="$vuetify.breakpoint.lgAndUp"
                app
        >
            <v-list dense>
                <template v-for="item in items">
                    <v-row
                            v-if="item.heading"
                            :key="item.heading"
                            align="center"
                    >
                        <v-col cols="6">
                            <v-subheader v-if="item.heading">
                                {
    
    {
    
     item.heading }}
                            </v-subheader>
                        </v-col>
                        <v-col
                                cols="6"
                                class="text-center"
                        >
                            <a
                                    href="#!"
                                    class="body-2 black--text"
                            >EDIT</a>
                        </v-col>
                    </v-row>
                    <v-list-group
                            v-else-if="item.children"
                            :key="item.text"
                            v-model="item.model"
                            :prepend-icon="item.model ? item.icon : item['icon-alt']"
                            append-icon=""
                    >
                        <template v-slot:activator>
                            <v-list-item-content>
                                <v-list-item-title>
                                    {
    
    {
    
     item.text }}
                                </v-list-item-title>
                            </v-list-item-content>
                        </template>
                        <v-list-item
                                v-for="(child, i) in item.children"
                                :key="i"
                                link
                        >
                            <v-list-item-action v-if="child.icon">
                                <v-icon>{
    
    {
    
     child.icon }}</v-icon>
                            </v-list-item-action>
                            <v-list-item-content>
                                <v-list-item-title>
                                    {
    
    {
    
     child.text }}
                                </v-list-item-title>
                            </v-list-item-content>
                        </v-list-item>
                    </v-list-group>
                    <v-list-item
                            v-else
                            :key="item.text"
                            link
                    >
                        <v-list-item-action>
                            <v-icon>{
    
    {
    
     item.icon }}</v-icon>
                        </v-list-item-action>
                        <v-list-item-content>
                            <v-list-item-title>
                                {
    
    {
    
     item.text }}
                            </v-list-item-title>
                        </v-list-item-content>
                    </v-list-item>
                </template>
            </v-list>
        </v-navigation-drawer>

        <v-app-bar
                :clipped-left="$vuetify.breakpoint.lgAndUp"
                app
                color="blue darken-3"
                dark
        >
            <v-app-bar-nav-icon @click.stop="drawer = !drawer" />
            <v-toolbar-title
                    style="width: 300px"
                    class="ml-0 pl-4"
            >
                <span class="hidden-sm-and-down">Google Contacts</span>
            </v-toolbar-title>
            <v-text-field
                    flat
                    solo-inverted
                    hide-details
                    prepend-inner-icon="mdi-magnify"
                    label="Search"
                    class="hidden-sm-and-down"
            />
            <v-spacer />
            <v-btn icon
                   @click="changeLang"
            >
                <v-icon>mdi-apps</v-icon>
            </v-btn>
            <v-btn icon>
                <v-icon>mdi-bell</v-icon>
            </v-btn>
            <v-btn
                    icon
                    large
            >
                <v-avatar
                        size="32px"
                        item
                >
                    <v-img
                            src="https://cdn.vuetifyjs.com/images/logos/logo.svg"
                            alt="Vuetify"
                    /></v-avatar>
            </v-btn>
        </v-app-bar>
        <v-content>
            <v-container
                    class="fill-height"
                    fluid
            >
                <v-row
                        align="center"
                        justify="center"
                >
                    <v-tooltip right>
                        <template v-slot:activator="{ on }">
                            {
    
    {
    
    $t('m.hello')}}
                        </template>
                        <span>Source</span>
                    </v-tooltip>
                </v-row>
            </v-container>
        </v-content>
        <v-btn
                bottom
                color="pink"
                dark
                fab
                fixed
                right
                @click="dialog = !dialog"
        >
            <v-icon>mdi-plus</v-icon>
        </v-btn>
        <v-dialog
                v-model="dialog"
                width="800px"
        >
            <v-card>
                <v-card-title class="grey darken-2">
                    Create contact
                </v-card-title>
                <v-container>
                    <v-row class="mx-2">
                        <v-col
                                class="align-center justify-space-between"
                                cols="12"
                        >
                            <v-row
                                    align="center"
                                    class="mr-0"
                            >
                                <v-avatar
                                        size="40px"
                                        class="mx-3"
                                >
                                    <img
                                            src="//ssl.gstatic.com/s2/oz/images/sge/grey_silhouette.png"
                                            alt=""
                                    >
                                </v-avatar>
                                <v-text-field
                                        placeholder="Name"
                                />
                            </v-row>
                        </v-col>
                        <v-col cols="6">
                            <v-text-field
                                    prepend-icon="business"
                                    placeholder="Company"
                            />
                        </v-col>
                        <v-col cols="6">
                            <v-text-field
                                    placeholder="Job title"
                            />
                        </v-col>
                        <v-col cols="12">
                            <v-text-field
                                    prepend-icon="mail"
                                    placeholder="Email"
                            />
                        </v-col>
                        <v-col cols="12">
                            <v-text-field
                                    type="tel"
                                    prepend-icon="phone"
                                    placeholder="(000) 000 - 0000"
                            />
                        </v-col>
                        <v-col cols="12">
                            <v-text-field
                                    prepend-icon="notes"
                                    placeholder="Notes"
                            />
                        </v-col>
                    </v-row>
                </v-container>
                <v-card-actions>
                    <v-btn
                            text
                            color="primary"
                    >More</v-btn>
                    <v-spacer />
                    <v-btn
                            text
                            color="primary"
                            @click="dialog = false"
                    >Cancel</v-btn>
                    <v-btn
                            text
                            @click="dialog = false"
                    >Save</v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>
    </v-app>
</template>

<script>
    export default {
    
    
        props: {
    
    
            source: String,
        },
        data: () => ({
    
    
            dialog: false,
            drawer: null,
            items: [
                {
    
     icon: 'mdi-contacts', text: 'Contacts' },
                {
    
     icon: 'mdi-history', text: 'Frequently contacted' },
                {
    
     icon: 'mdi-content-copy', text: 'Duplicates' },
                {
    
    
                    icon: 'mdi-chevron-up',
                    'icon-alt': 'mdi-chevron-down',
                    text: 'Labels',
                    model: true,
                    children: [
                        {
    
     icon: 'mdi-plus', text: 'Create label' },
                    ],
                },
                {
    
    
                    icon: 'mdi-chevron-up',
                    'icon-alt': 'mdi-chevron-down',
                    text: 'More',
                    model: false,
                    children: [
                        {
    
     text: 'Import' },
                        {
    
     text: 'Export' },
                        {
    
     text: 'Print' },
                        {
    
     text: 'Undo changes' },
                        {
    
     text: 'Other contacts' },
                    ],
                },
                {
    
     icon: 'mdi-settings', text: 'Settings' },
                {
    
     icon: 'mdi-message', text: 'Send feedback' },
                {
    
     icon: 'mdi-help-circle', text: 'Help' },
                {
    
     icon: 'mdi-cellphone-link', text: 'App downloads' },
                {
    
     icon: 'mdi-keyboard', text: 'Go to the old version' },
            ],
        }),
        methods:{
    
    
            changeLang(){
    
    
                this.$i18n.locale = 'en'
            }
        }
    }
</script>

此模板为 Vuetify 的预制布局,我新建了一个 changeLang() 方法,将英文输出转为中文输出,并且第 99 行给一个按钮绑定了点击事件,当用户点击按钮后将激活 changeLang() 方法,完成语言的切换。

编译资源

npm run dev

在这里插入图片描述
浏览器输入我们的项目地址:http://www.hypercell.com 查看运行结果:

Vuetify 首秀 !

在这里插入图片描述

点击右上角的魔方图标,屏幕中间的 “你好” 就变成了 “hello” ,说明我们的 Vue-i18n 国际化也配置成功了。

版本提交

到此完成了项目的初始化工作,以后的工作就是在此基础上添枝加叶。

git add -A
git commit -m "初始化 Vue.js"

猜你喜欢

转载自blog.csdn.net/geeksoarsky/article/details/106728813