欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-03 20:49:48
...

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

Laravel+Vuetify 前后端分离项目中 Vue.js 的初始化
浏览器输入我们的项目地址:http://www.hypercell.com 查看运行结果:

Vuetify 首秀 !

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

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

版本提交

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

git add -A
git commit -m "初始化 Vue.js"
相关标签: MVVM设计模式