美文网首页Angular学习实践我爱编程
使用.net core ABP和Angular模板构建博客管理系

使用.net core ABP和Angular模板构建博客管理系

作者: 易兒善 | 来源:发表于2017-11-09 20:47 被阅读91次

    返回目录

    初步实现编辑更新功能

    新建一个edit-note模块如下:

    编辑模块

    我们看看作者的新建页面用到了什么,
    用到了ngx-bootstrap的弹出层。官网地址: https://valor-software.com/ngx-bootstrap/#/modals#modal-directive
    然后是一个基类AppComponentBase

    edit-user.component.ts

    在我们页面引入相关组件

    import { Component, ViewChild, Injector, Output, EventEmitter, ElementRef } from '@angular/core';
    import { ModalDirective } from 'ngx-bootstrap';
    import {NoteServiceService, NoteDto, UpdateNoteDto} from '@app/blog/note-service.service';
    import { AppComponentBase } from '@shared/app-component-base';
    

    定义一些东西

    export class EditNoteComponent extends AppComponentBase {
        active = false; // 弹出层内容是否有效
        note: UpdateNoteDto; // 编辑的文章
        preViewContent = ''; // 文章预览内容,转换层html后的
        @ViewChild('editNoteModal') modal: ModalDirective;  // 弹出层
        @ViewChild('modalContent') modalContent: ElementRef; // 弹出层内的内容
    
        @Output() modalSave: EventEmitter<any> = new EventEmitter<any>(); // 页面间传值,这相当于一个自定义事件
      constructor(injector: Injector, private noteServer: NoteServiceService) {
          super(injector);
      }
    // 显示
        show(id: number): void {
            this.noteServer.GetNote(id).subscribe(m => {
                this.note = m;
                this.active = true;
                this.modal.show();
            });
        }
        // 关闭
        close(): void {
            this.updateNote();
            this.active = false;
            this.modal.hide();
        }
    
        // 更新
        updateNote(): void {
            this.noteServer.Update(this.note).subscribe(m => {
    
            });
        }
    
    }
    

    edit-note.component.html编辑页面初步布局如下

    <div bsModal #editNoteModal="bs-modal" class="modal fade"  tabindex="-1" role="dialog" aria-labelledby="editNoteModal" aria-hidden="true" [config]="{backdrop: 'static'}">
        <div class="container">
    
            <div #modalContent>
                <div *ngIf="active">
                    <div class="m-editer-area">
                        <!--************* 顶部,文章标题和一些菜单  ****************-->
                        <header>
                            <div class="u-title">
                                <input type="text" [(ngModel)]="note.title" class="form-control">
                            </div>
                        </header>
                        <!--************* 中间部分,编辑和预览区域  ****************-->
                        <section>
                            <!--************* 中间部分左边,编辑区域  ****************-->
                            <div class="u-wirte z-half">
                                <textarea id="editer" [(ngModel)]="note.content"></textarea>
                            </div>
                            <!--************* 中间部分右边,预览区域  ****************-->
                            <div class="u-view z-half">
                                <article [innerHTML]="preViewContent"></article>
                            </div>
                        </section>
                        <!--************* 底部,  ****************-->
                        <footer>
                            <div class="u-count">
                                <p>共{{note.content.length}}字节</p>
                            </div>
                            <div class="u-menu">
                                <a>发布</a>
                                <a (click)="close()">关闭</a>
                            </div>
                        </footer>
                    </div>
                </div>
            </div>
    
        </div>
    </div>
    
    
    

    我们在edit-note.component.css写点样式

    .m-editer-area {
        position: absolute;
        top: 10%;
        left: 10%;
        right: 10%;
        background: rgba(91, 28, 111, 0.8);
        transition: all .5s;
    }
    .m-editer-area header, .m-editer-area footer {
        text-align: right;
        font-size: 0;
    }
    .m-editer-area a {
        display: inline-block;
        width: 50px;
        height: 50px;
        line-height: 50px;
        text-align: center;
        font-size: 15px;
        cursor: pointer;
        color: #fff;
        transition: all .5s;
    }
    .m-editer-area a:hover {
        background: rgba(0,0,0,0.2);
    }
    .m-editer-area a.z-atv {
        color: #dd3c1f;
        background: rgba(255,255,255,0.8);
    }
    .m-editer-area footer a {
        padding: 0 10px;
    }
    
    .m-editer-area footer a:active, a.u-screen-tab:active {
        background: #dd3c1f;
        color: #fff;
        transition: none;
    }
    .m-editer-area footer p {
        float: left;
        line-height: 50px;
        margin-left: 15px;
        color: #fff;
    }
    .m-editer-area section {
        position: relative;
        height: 400px;
        background: #fff;
        overflow: hidden;
    }
    .m-editer-area section>div {
        transition: all .5s;
    }
    .u-wirte {
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
    }
    .u-wirte textarea {
        width: 98%;
        height: 100%;
        padding: 0 1%;
        line-height: 150%;
        border: none;
        outline: none;
        resize: none;
        font-size: 15px;
        font-family: "微软雅黑"
    }
    
    .u-view {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        overflow: auto;
        padding: 1%;
        background: #fff;
        box-shadow: 0 0 10px #000 inset;
        transform: translateX(100%);
    }
    
    .u-view article {
        padding: 0;
        background: transparent;
    }
    
    .u-view.z-half {
        left: 50%;
        transform: translateX(0);
    }
    
    .u-wirte.z-half {
        right: 50%;
    }
    
    .u-view.z-atv {
        transform: translateX(0);
    }
    
    .z-full {
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        margin-top: 0;
    }
    
    .z-full section {
        position: absolute;
        top: 50px;
        left: 0;
        bottom: 50px;
        right: 0;
        height: auto;
    }
    
    .z-full footer {
        position: absolute;
        bottom: 0;
        width: 100%;
    }
    header {
        padding:10px 0;
    }
    header .u-title{
        width: 65%;
    }
    header .u-title input{
        background-color: transparent;
        color: whitesmoke;
        border: none;
    }
    footer .u-count{
        width: 20%;
        float: left;
        color: white;
        font-size: 16px;
    }
    footer .u-menu{
        width: 70%;
        float: right;
    }
    footer .u-menu *{
        float: right;
    }
    
    

    引用编辑功能

    在note.component.ts中如下使用。添加引用,添加编辑方法。

    import {EditNoteComponent} from '@app/blog/note/edit-note/edit-note.component';
    
    
    
    @ViewChild('editNoteModal') editNoteModal: EditNoteComponent;
       editNote(note: NoteDto) {
           this.editNoteModal.show(note.id);
       }
    
    

    在 note.component.html中添加模块并调用editNote()

     <ul class="dropdown-menu pull-right">
        <li><a href="javascript:void(0);" class="waves-effect waves-block" (click)="editNote(note)"><i class="material-icons">create</i>编辑</a></li>
        <li><a href="javascript:void(0);" class="waves-effect waves-block" (click)="delete(note)"><i class="material-icons">delete_sweep</i>删除</a></li>
    </ul>
    
    <app-edit-note #editNoteModal ></app-edit-note>
    
    简单实现

    可以看出来还有很多不足,后面一点一点来完善。

    • 返回列表后也没有自动更新
    • 预览处也没实现实时预览
    • 自动更新也没有实现
    • 发布功能还没有实现
    • 界面不够美观

    返回列表更新

    这个就要用到angular的父子页面传值。
    还记得之前定义了@Output() modalSave: EventEmitter<any> = new EventEmitter<any>();这个还没有用么。

        // 关闭
        close(): void {
            this.updateNote();
            this.active = false;
            this.modal.hide();
            this.modalSave.emit(this.note.title); // 我们这里还可以传一个值过去
        }
    

    在note模块中做如下修改

    <app-edit-note #editNoteModal (modalSave)="test($event)"></app-edit-note>
    
    
       // 测试父子页面传值
       test(e) {
           alert(e);
           this.refresh();
       }
    
    测试父子页面传值

    实现实时预览

    我们之前设计是使用markdown语法来制作这个编辑功能。我们选用marked组件来帮助我们,使用参考:https://www.npmjs.com/package/marked
    安装marked

    cnpm install marked --save
    

    引入

    import marked from 'marked';
    

    使用

        // 显示
        show(id: number): void {
            this.noteServer.GetNote(id).subscribe(m => {
                this.note = m;
                this.active = true;
                this.modal.show();
                this.preViewContent = marked(this.note.content);
            });
        }
    
    预览有了,但是没有实时同步

    要实现实时同步,我们使用angular的FormControl来帮忙

    import { FormControl } from '@angular/forms';
    import 'rxjs/add/operator/debounceTime';  // 触发间隔
    import 'rxjs/add/operator/distinctUntilChanged'; // 防止触发两次
    
      term = new FormControl();
    
        // 显示
        show(id: number): void {
            this.noteServer.GetNote(id).subscribe(m => {
                this.note = m;
                this.active = true;
                this.modal.show();
                this.term.valueChanges  // 监测输入文本框的变化同步更新预览 400ms
                    .debounceTime(400)
                    .distinctUntilChanged()
                    .subscribe(term => {
                       this.preViewContent = marked(this.note.content);
                    });
            });
        }
    
    

    页面修改

    <div class="u-wirte z-half">
          <textarea id="editer" [(ngModel)]="note.content" [formControl]="term"></textarea>
     </div>
    

    别忘记app.module.ts中也需要引入ReactiveFormsModule

    import { FormsModule, ReactiveFormsModule} from '@angular/forms';
    
        imports: [
            ReactiveFormsModule,
            FormsModule,
        ],
    
    同步预览

    自动更新到服务器

    上面都做到了,自动更新就简单了

        // 显示
        show(id: number): void {
            this.noteServer.GetNote(id).subscribe(m => {
                this.note = m;
                this.active = true;
                this.modal.show();
                this.term.valueChanges  // 监测输入文本框的变化同步更新预览 400ms
                    .debounceTime(400)
                    .distinctUntilChanged()
                    .subscribe(term => {
                        this.preViewContent = marked(this.note.content);
                    });
                this.term.valueChanges  // 30s自动保存到服务器
                    .debounceTime(1000 * 30)
                    .subscribe(t => this.updateNote());
            });
        }
    
    

    实现发布功能

        // 发布
        publicNote(): void {
            this.note.img = 'http://img0.imgtn.bdimg.com/it/u=313511342,2661546070&fm=27&gp=0.jpg';
            this.note.des = '我实在太懒了,添加描述的功能还没有来得及开发,而且这两个字的我后台设置的是必填字段';
            this.noteServer.PublicNote(this.note).subscribe(m => {
                this.active = false;
                this.modal.hide();
                this.modalSave.emit(null);
            });
        }
    

    简单优化

    将新建方法修改如下:

       createNote() {
           const input = new CreateNoteDto();
           input.textType = 0;
           this.noteService.Create(input).subscribe(m => {
               this.editNote(m);
           });
       }
    

    编辑页面的样式也做了调整,这里就不一一写了。最后效果如下:

    1.gif

    好项目是慢慢优化出来的,一口是吃不出一个大胖子来的,慢慢优化,一步步行动起来,才能遇见更好的自己。

    • 在操作等待的时候没有遮罩层,这种体验很不好。
    • 操作成功或者失败也没有提示。

    相关文章

      网友评论

      • 1d38f55f2b39:note-service.service 这个文件也没有呢
        易兒善:@明明_6f47 在前面的文章里写了的
      • 1d38f55f2b39:note.component.css 文件怎么没有看到?有些步骤您省略了,直接弄点源码下载就好了

      本文标题:使用.net core ABP和Angular模板构建博客管理系

      本文链接:https://www.haomeiwen.com/subject/czhemxtx.html