使用Vue.Draggable和laravel實(shí)現(xiàn)拖動(dòng)改變順序

項(xiàng)目演示

drag.gif

準(zhǔn)備工作

  1. 新建laravel項(xiàng)目
laravel new drag
composer install
npm install 

2.安裝Vue.Draggabel

npm install vuedraggable 

數(shù)據(jù)準(zhǔn)備

  • 建立series
php artisan make:model Series -m  -c -r

-m:生成migration文件
-c生成controller
-r 生成個(gè)resource controller

migration文件

Schema::create('series', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->timestamps();
        });
  • 建立parts
php artisan make:model Parts -m 

migration文件

 Schema::create('parts', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('series_id')->unsigned();
            $table->string('title');
            $table->integer('sort_order');
            $table->timestamps();
        });

Series.php建立關(guān)系

public function parts()
    {
        return $this->hasMany(Part::class)->orderBy('sort_order','asc');
    }

使用Seeder填充數(shù)據(jù)

php artisan make:seeder SeriesTableSeeder
php artisan make:seeder PartsTableSeeder

SeriesTableSeeder.php

 $faker = Faker::create();
 Series::create([
     'title'=>$faker->text(10)
 ]);

PartsTableSeeder.php

$faker = Faker::create();
        for($i=1;$i<5;$i++){
            \App\Part::create([
                'title'=>'Task'.$i,
                'series_id'=>1,
                'sort_order'=>$i
            ]);
        }

使用編寫前臺(tái)代碼并且使用Vue.Draggable

<div class="panel panel-default">
                    <div class="panel-heading">Editing <em>{{title}}</em></div>
                    
                    <div class="panel-body">
                        <div class="alert alert-success" v-if="message">
                            {{message}}
                        </div>
                        <form action="#" @submit.prevent="submit">
                            <div class="form-group" v-bind:class="{'has-error':errors.title}">
                                <label for="title" class="control-label">Title</label>
                                <input type="text" name="title" id="title" class="form-control" v-model="title" >
                                <div class="help-block" v-if="errors.title">
                                    {{errors.title[0]}}
                                </div>
                            </div>
                            <draggable :list="parts" :options="{'handle':'.panel-heading'}" @start="drag=true" @end="drag=false " @change="update">
                            <div class="panel panel-default" v-for="part,index in parts">
                                <div class="panel-heading">Part {{index + 1}}({{part.sort_order}})</div>
                                <div class="panel-body">
                                    <div class="form-group" v-bind:class="{'has-error':errors['parts.'+index+'.title']}">
                                        <label>Part Title</label>
                                        <input type="text" name="" id="" class="form-control" v-model="part.title">
                                        <div class="help-block" v-if="errors['parts.'+index+'.title']">
                                            {{errors['parts.'+index+'.title'][0]}}
                                        </div>
                                    </div>
                                </div>
                            </div>
                            </draggable>
                            <div class="form-group">
                                <button type="submit" class="btn btn-primary">Save</button>
                            </div>
                        </form>
                    </div>
                </div>
<script>
    import draggable from 'vuedraggable';
    export default {
        components:{
            draggable
        },
        data(){
            return {
                title: null,
                parts: [],
                errors:[],
                message:null
            }
        },
        props: [
            'data'
        ],
        mounted() {
            this.title = this.data.title;
            this.parts = this.data.parts;
        },
        methods:{
            update(e){
                this.parts.map((part,index)=>{
                    part.sort_order = index + 1
                })
            },
            submit(){
                axios.patch('/series/'+this.data.id,{
                    title:this.title,
                    parts:this.parts
                }).then((response)=>{
                    this.message="Series saved!"
                }).catch((error)=>{
                    this.errors=error.response.data
                })
            }
        }
    }
</script>

后端代碼編寫

1.路由文件web.php

Route::get('/series/{series}/edit','SeriesController@edit');
Route::patch('/series/{series}','SeriesController@update');

2.生成數(shù)據(jù)驗(yàn)證

php artisan make:request UpdateSeriesFormRequest
 public function rules()
    {
        return [
            'title' => 'required',
            'parts.*.title' => 'required'
        ];
    }
    public function messages()
    {
        return [
            'title.required' => 'You must enter a series title',
            'parts.*.title.required'=> 'You need to give this part a title'
        ];
    }

3.創(chuàng)建隊(duì)列任務(wù)

php artisan queue:table
php artisan queue:failed-table
php artisan make:job UpdateSeriesParts
 public function __construct(Series $series,$parts)
    {
        //
        $this->series = $series;
        $this->parts = $parts;
    }
public function handle()
    {
        $this->series->parts->each(function ($part,$index) {
            $part->update(array_only($this->parts[$index],['title','sort_order']));
        });
    }

開啟隊(duì)列監(jiān)聽

php artisan queue:listen 

4.Controller文件

public function edit(Series $series)
    {
        $series->load('parts');
        return view('series.edit',compact('series'));
    }
public function update(UpdateSeriesFormRequest $request, Series $series)
    {
        
        $series->title=$request->title;
        $series->save();
        dispatch(new UpdateSeriesParts($series,$request->parts));
        return response(null,200);
    }

這是codecourse上的Demo,使用了Vue作為前端,Vue.draggable實(shí)現(xiàn)拖動(dòng),axios發(fā)送請(qǐng)求(laravel5.4現(xiàn)在默認(rèn)就是axios)后端使用Laravel冀值,包括數(shù)據(jù)填充,數(shù)據(jù)驗(yàn)證,建立模型,隊(duì)列等效知識(shí)點(diǎn),希望有助于大家今后用laravel和vue做開發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颤难,一起剝皮案震驚了整個(gè)濱河市鸿脓,隨后出現(xiàn)的幾起案子历筝,更是在濱河造成了極大的恐慌,老刑警劉巖篙挽,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件目养,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡财异,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門唱遭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戳寸,“玉大人,你說我怎么就攤上這事拷泽∫呷担” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵司致,是天一觀的道長拆吆。 經(jīng)常有香客問我,道長脂矫,這世上最難降的妖魔是什么枣耀? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮庭再,結(jié)果婚禮上捞奕,老公的妹妹穿的比我還像新娘。我一直安慰自己拄轻,他們只是感情好颅围,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恨搓,像睡著了一般院促。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斧抱,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天常拓,我揣著相機(jī)與錄音,去河邊找鬼辉浦。 笑死墩邀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盏浙。 我是一名探鬼主播眉睹,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼荔茬,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了竹海?” 一聲冷哼從身側(cè)響起慕蔚,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斋配,沒想到半個(gè)月后孔飒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艰争,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年坏瞄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甩卓。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸠匀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逾柿,到底是詐尸還是另有隱情缀棍,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布机错,位于F島的核電站爬范,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弱匪。R本人自食惡果不足惜青瀑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萧诫。 院中可真熱鬧狱窘,春花似錦、人聲如沸财搁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尖奔。三九已至搭儒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間提茁,已是汗流浹背淹禾。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茴扁,地道東北人铃岔。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親毁习。 傳聞我的和親對(duì)象是個(gè)殘疾皇子智嚷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容