上次我用 laravel5.3 + Vue 开发了一个简单的单页应用,这次我打算将其升级到 laravel5.5,在升级的过程中,做一下记录,其源码放在 github 上面,源码地址

 

开发环境

软件包 版本
Laravel 5.5
Vue > 2.5.7
axios > 0.17
vue-router > 3.0.1
vuex > 3.0.1
 

安装

# 安装 laravel
composer create-project --prefer-dist laravel/laravel laravel-vue "5.5.*" # 安装前端依赖包
npm install

安装完之后,为了便于开发,使用热更新模式。

# 在 webpack.mix.js 中添加配置
mix.browserSync({
proxy: 'localhost:8000'
}); # 执行 `php artisan serve`
php artisan serve # 执行 npm run watch
npm run watch

打开浏览器访问 http://localhost:3000 就可以看到 laravel 的欢迎页面了

 

目标

开发三个页面,首页,列表,详情,相对应准备 3 个 api 接口

 

migration

php artisan make:migration news --create=news
# database/migrations/create_news.php
Schema::create('news', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('content');
$table->integer('is_recommend')->default(0);
$table->timestamps();
});
 

model

这里使用命令生成 model 文件,编辑对应的文件内容。

php artisan make:model News
# app/News.php
namespace App; use Illuminate\Database\Eloquent\Model; class News extends Model
{
public $fillable = ['title', 'content'];
}
 

controller

生成控制器,在控制器中定义三个接口对应的方法。

php artisan make:controller NewsController
# app/Http/Controllers/NewsController
<?php
namespace App\Http\Controllers; use Illuminate\Http\Request;
use App\News; class NewsController extends Controller
{
/**
* 推荐列表
*/
public function recommend()
{
$list = News::where('is_recommend', 1)->get();
foreach ($list as $key => $value) {
$list[$key]->created = $list[$key]->created_at->diffForHumans();
}
return $list;
} /**
* 新闻列表
*/
public function index()
{
$list = News::get();
foreach ($list as $key => $value) {
$list[$key]->created = $list[$key]->created_at->diffForHumans();
}
return $list;
} /**
* 新闻详情
*/
public function show($id)
{
$row = News::findOrFail($id);
return $row;
}
}
 

router

定义 api 的接口路由,在 routes/api.php 文件中定义。

# routes/api.php
Route::get('/news', 'NewsController@index');
Route::get('/news/recommend', 'NewsController@recommend');
Route::get('/news/{id}', 'NewsController@show');
 

Vue单页

到这里我们准备工作已经完毕,接下来正式开发 Vue 的单页应用,在开发单页应用中,对应 Route ApiVuex Components 这些,下面我们就来定义这些。

首先在首页引入对应的 app.css 和 app.js 文件。

# resource/vies/welcome.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="csrf-token" content="@{{ csrf_token }}">
<title>Laravel & Vue</title>
<link rel="stylesheet" type="text/css" href="/css/app.css">
</head>
<body>
<div id="app">
<nav class="navbar navbar-inverse">
<div class=" container">
<div class="navbar-header">
<a class="navbar-brand" href="/">LaravelVue</a>
</div>
</div>
</nav>
<div class="container main">
<router-view />
</div>
</div>
<script type="text/javascript" src="/js/app.js"></script>
</body>
</html>
 

配置启动 app.js

应用对应的入口文件是 app.js,所以在这个入口文件中,我们实例化 Vue 实例,初始化和加载所需的组件。

# resource/assets/js/app.js
require('./bootstrap'); window.Vue = require('vue'); import VueRouter from 'vue-router';
Vue.use(VueRouter);
import store from './store/'; // vuex 数据存储所需对象
import routes from './routes'; // 路由配置文件
// 实例化路由
const router = new VueRouter({
routes
}) var vm = new Vue({
store,
router
}).$mount('#app');
 

路由

前端页面主要有 3 个路由,如下

# resource/assets/js/routes.js
export default[
{ path: '', redirect: '/index' },
{ path: '/index', component: require('./page/App.vue') },
{ path: '/list', component: require('./page/List.vue') },
{ path: '/detail/:id', component: require('./page/Detail.vue') }
];
 

Vuex

Vuex 集中式存储管理应用的所有组件的状态,这里使用的是多模块方式记录数据。

# resource/assets/js/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import news from './news';
Vue.use(Vuex);
export default new Vuex.Store({
// 可以设置多个模块
modules: {
news
}
}); # resource/assets/js/store/news.js
import api from '../api';
export default{
state: {
recommend: [], // 推荐
lists: [], // 列表
detail: {} // 详情
},
mutations: {
// 注意,这里可以设置 state 属性,但是不能异步调用,异步操作写到 actions 中
SETRECOMMEND(state, lists) {
state.recommend = lists;
},
SETLISTS(state, lists) {
state.lists = lists;
},
SETDETAIL(state, detail) {
state.detail = detail;
}
},
actions: {
getNewsDetail({commit}, id) {
// 获取详情,并调用 mutations 设置 detail
api.getNewsDetail(id).then(function(res) {
commit('SETDETAIL', res.data);
document.body.scrollTop = 0;
});
},
getNewsRecommend({commit}) {
api.getNewsRecommend().then(function(res) {
commit('SETRECOMMEND', res.data);
});
},
getNewsLists({commit}) {
api.getNewsLists().then(function(res) {
commit('SETLISTS', res.data);
});
}
}
}
 

api

我们在这里定义前端请求数据 api,这里使用的是 axios 包来请求数据,具体用法参考文档。

# resource/assets/js/api.js
import axios from 'axios'
export default {
// 首页推荐接口
getNewsRecommend: function (params) {
return axios.get('api/news/recommend', {
params: params
})
},
// 列表接口
getNewsLists: function (params) {
return axios.get('api/news', {
params: params
})
},
// 详情接口
getNewsDetail: function (id) {
return axios.get('api/news/' + id)
}
}
 

page

我们在这里定义组件页面,将其页面放到 page 目录下面,Vue 定义组件的方式参考文档。
三个页面的具体写法定义如下:

# resource/assets/js/page/App.vue
<template>
<div class="panel panel-default">
<div class="panel-heading">新闻推荐
<router-link to="/list" class="pull-right">更多</router-link>
</div>
<ul class="list-group">
<li class="list-group-item"
v-for="row in recommend">
<router-link :to="{path:'/detail/' + row.id}">
{{ row.title }}
</router-link>
<span class="pull-right">{{ row.created }}</span>
</li>
</ul>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default({
// 映射 vuex 上面的属性
computed: mapState({
recommend: state => state.news.recommend
}),
created() {
// 获取推荐列表
this.getNewsRecommend();
},
methods: {
// 映射 vuex 对象上的方法
...mapActions([
'getNewsRecommend'
])
}
});
</script> # resource/assets/js/page/List.vue
<template>
<div class="panel panel-default">
<div class="panel-heading">新闻列表</div>
<ul class="list-group">
<li class="list-group-item"
v-for="row in lists">
<router-link :to="{path:'/detail/' + row.id}">
<span class="label label-success" v-if="row.is_recommend">推荐</span>
{{ row.title }}
</router-link>
<span class="pull-right">{{ row.created }}</span>
</li>
</ul>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default({
computed: mapState({
lists: state => state.news.lists
}),
created() {
this.getNewsLists();
},
methods: {
...mapActions([
'getNewsLists'
])
}
});
</script> # resource/assets/js/page/Detail.vue
<template>
<div>
<ol class="breadcrumb">
<li><a href="/">首页</a></li>
<li><router-link to="/list" class="pull-right">新闻</router-link></li>
<li class="active">{{ detail.title }}</li>
</ol>
<h3><span class="label label-success" v-if="detail.is_recommend">推荐</span> {{ detail.title }}</h3>
<p>创建时间:{{ detail.created_at }}</p>
<div>
{{ detail.content }}
</div>
</div>
</template>
<style>
.breadcrumb{
padding: 8px 0;
}
</style>
<script>
import { mapState, mapActions } from 'vuex';
export default({
computed: mapState({
detail: state => state.news.detail
}),
created() {
// 获取路由参数id
// js 中用 this.$route 获取当前路由,用 this.$router 获路由对象,全部路由信息
// 在模板中用 $router 和 $router 直接调用
var id = this.$route.params.id;
this.getNewsDetail(id);
},
methods: {
...mapActions([
'getNewsDetail'
])
}
});
</script>

这里我们简单的单页应用就开发完毕了,使用 npm run watch 可以热更新,实时看到页面的变化。
文章地址

Laravel 5.5 + Vue 开发单页应用的更多相关文章

  1. 【前端vue开发架构】vue开发单页项目架构总结

    为营销活动设计的前端架构 主要的技术栈为 Vuejs,Webpack,请自行阅读如下技术或者框架的文档: 一.基础说明: node (https://nodejs.org/en/) npm (http ...

  2. 使用Vue快速开发单页应用

    本文所涉及代码全在vue-cnode 单页应用,即在一个页面集成系统中所有功能,整个应用只有一个页面.因为路由的控制在前端,单页面应用在页面切换时比传统页面更快,从而在前端体验更好. 将逻辑从后端转移 ...

  3. 填坑:在 SegmentFault 开发单页应用之图片引用的问题探索

    前言 前段时间,SegmentFault 低调上线了 技术号 模块,方便用户对数据进行集中管理.在开发过程中,第一次引入了 MV* 框架. SF 的基本架构还是后端路由,这也使得页面频繁地整体请求,体 ...

  4. EasyDSS高性能流媒体服务器前端重构(五)- webpack + vue-router 开发单页面前端实现按需加载 - 副本

    为了让页面更快完成加载, 第一时间呈现给客户端, 也为了帮助客户端节省流量资源, 我们可以开启 vue-router 提供的按需加载功能, 让客户端打开页面时, 只自动加载必要的资源文件, 当客户端操 ...

  5. PHP 将数据从 Laravel 传送到 vue 的四种方式

    在过去的两三年里,我一直在研究同时使用 Vue 和 Laravel 的项目,在每个项目开发的开始阶段,我必须问自己 “我将如何将数据从 Laravel 传递到 Vue ?”.这适用于 Vue 前端组件 ...

  6. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器前端重构(五)- webpack + vue-router 开发单页面前端实现按需加载

    为了让页面更快完成加载, 第一时间呈现给客户端, 也为了帮助客户端节省流量资源, 我们可以开启 vue-router 提供的按需加载功能, 让客户端打开页面时, 只自动加载必要的资源文件, 当客户端操 ...

  7. 实现Vue的多页签组件

    在之前的博客中  关于vue的多页面标签功能,对于嵌套router-view缓存的最终无奈解决方法  有写过vue的多页签功能的解决方案 可以看到我当时那个多页签的组件还是比较简单 的,只有打开跟关闭 ...

  8. 做一个gulp+webpack+vue的单页应用开发架子

    1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...

  9. angular开发单页面应用--页面资源部分

    关于angular是什么,能够干什么就不在这里解释了,自行搜索了,或者等稍晚一点再解释... angular适合开发单页面应用,这句话在介绍angular的网站和博客里都可以提到.因为angular是 ...

随机推荐

  1. support:design:26.1.0

    https://blog.csdn.net/qzltqdf3179103/article/details/79583491 compileSdkVersion 26buildToolsVersion ...

  2. idea 修改 使用的git账号

    打开控制面板-->用户账户-->凭证管理器 如下图点击进入,删除原有的账号 当在idea中再提交或下载代码时,就会弹出如下提示框: 重新输入你自己的账号就可以了.

  3. 带轮播图、导航栏、商品的简单html,以及轮播图下边数字随轮播图的改变而改变

    ---恢复内容开始--- 在做这个的时候,最不会的是中间轮播图下边的数字是如何实现转变的,后来加入了jQuery就能实现了. css部分: <style type="text/css& ...

  4. cakePHP的ajax弹出窗

    在html里添加一个触发弹出框的按钮 $("#button1").on("click", function() { $("#dialogue" ...

  5. SSM的例子-参考

    ssm的例子:http://blog.csdn.net/double030/article/details/63683613

  6. java初学网站

    http://www.jfinal.com/doc http://www.w3school.com.cn/

  7. selenimu学习二

    1.上传文件 from selenium import webdriver import time import os driver = webdriver.Chrome() src_file = & ...

  8. Django xadmin后台添加富文本编辑器UEditor的用法

    效果图: 步骤: 1.利用命令:pip install DjangoUeditor,安装DjangoUeditor,但由于DjangoUeditor没有python3版本的,从的Github上把修改好 ...

  9. 有关https有的网站可以访问有的访问不了的问题

    在开发中遇到这种情况,在开发工具里面访问可以,当时到了手机上之后就发现有的请求可以正常获取数据,有的则不行. 都是使用https地址,也配置后台了,但是就是不出数据,总是无法请求服务. 后来检查在手机 ...

  10. C#中多线程的并行处理

    System.Threading.Tasks,在该命名空间下Task是主类,表示一个类的异步的并发的操作,创建并行代码的时候不一定要直接使用Task类,在某些情况下可以直接使用Parallel静态类( ...