Vue-Cloudnotes教程.md

  • 需求分析
  • 前后端接口约定
  • 创建远程仓库
  • vue-cli初始化项目结构
  • 初始化样式
  • 引入图标
  • 安装less
  • 配置路由
  • 组件拆分
  • 划分模块,编写静态页面
  • 引入axios,封装接口api
  • mock数据,测试接口api
  • 再次分析交互的实现细节
  • 交互实现
  • 打包上线

交互分析

  • 当用户访问任意页面,假如用户未登录,跳转到登录页面
  • 用户此时可输入账号密码进行登录,也可点击注册账号显示【注册页面】
  • 在注册页面用户可输入账号密码进行登录
  • 登录成功后,跳转到【笔记本列表】页面,用户可以添加,删除、修改笔记本
  • 用户点击某条笔记本,会跳转到【笔记页面】,【笔记】页面展示【当前笔记本下】的笔记列表,【笔记详情组件】展示笔记列表下的第一条笔记详情;如果笔记列表为空,【详情组件】提示请新建。
  • 用户可切换笔记本,当切换后,【详情组件】默认展示第一条笔记

2.前后端接口约定

3.新建git仓库

4. Vue-cli建立项目结构

vue init webpack Vue-cloudnotes

5.项目代码初始化

1.在src/assets/styles目录下添加reset.css文件
2.在main.js里面引入reset.css

项目代码初始化.png

在main.js引入reset.png

6. 引入图标,初始化body

@import '//at.alicdn.com/t/font_496303_kqrjhri8l25d0a4i.css';
* {
  box-sizing: border-box;
}

html, body, #app {
  height: 100%;
}

body {
   font-family: 'Avenir', Helvetica, Arial, sans-serif;
  font-size: 14px;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;  
  background-color: #eee;
}

7.配置路由

在router-index.js里面配置路由

export default new Router({
  routes: [
    {
      path: '/',
      component: Login
    }, {
      path: '/login',
      name: 'Login',
      component: Login
    }, {
      path: '/notebooks',
      name: 'Notebooks',
      component: Notebooks
    }, {
      path: '/notes',
      name: 'Notes',
      component: Notes
    }, {
      path: '/trash',
      name: 'Trash',
      component: Trash
    }
  ]
})

组件拆分及注入

组件拆分.png
引入avatar组件1.png
引入avatar组件.png
使用avatar3.png

书写静态页面

使用?传参,再次配置路由

交互实现

在MVVM中,交互实现主要就是对数据的操作,我们对各部分需要用的的数据进行分析。

侧边栏
data:{username,slug}
用户头像
data:{slug}
sulg随着用户的改变而改变,初次进入为未登录,登录或注册后,用户发生改变;【slug】也要进行改变;
笔记本列表页
data:{notebooks}
每个用户状态下只有一个notebooks,随着用户改变而改变;
笔记页
data:{notebooks,curnotebook,notes,curnote}
notebooks通过getter获取,
curnotebook可以在笔记本列表点击导航改变;也可以在笔记侧边栏改变,依赖curbookId;
当用户改变notebook,notes随之改变
curnote,当用户在侧边栏点击可改变,未点击状态下为当前所有笔记中的第一个;点击后传入【curNoteId】改变;

使用Vuex管理数据

1.安装vuex
npm i vue-x --save
2.在src目录下新建store文件夹

vuex项目结构.png

3.在index中,引入相关模块

import Vue from 'vue'
import Vuex from 'vuex'
import note from './modules/notebook'
import notebook from './modules/note'
import user from './modules/user'
import trash from './modules/trash'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    notebook,
    note,
    user,
    trash
  }
})

4.在main.js中引入并使用Store;

import store from ''./store"

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

user.js

const state = {
    user:null
}
const getters = {
  sulg: state=>state.user?state.user.username.charAt(0):'未'

}
const mutations = {
  setUser(state,payload){
    state.user = payload
  }
}
const actions = {
checkoutLogin({commit}){
  return Auth.getInfo().then(res=>{
if(res.isLogin){
   commit('setUser',res.data)
    route.push('/notebooks')
  }else{
     route.push('/login')
  }
   
  })
},
  // 当login时改变user
  loginUser({commit},{username,password}) {
    return Auth.login({username,password}).then(res=>{
        commit('setUser',res.data);
        route.push('/notebooks')
    })
  },
  registerUser({commit},{username,password}) {
    return Auth.login({username,password}).then(res=>{
      commit('setUser',res.data);
      route.push('/notebooks')
      })
  }
}

export default {
state,
getters,
mutations,
actions
}

notebooks

import Notebook from '@/apis/notebooks'
import {Message} from 'element-ui'

const state = {
  notebooks:  [],
  curBookId: null,
}
const getters = {
  notebooks: state=>state.notebooks,
  curBook: state=> {
    if(!state.curBookId) return state.notebooks[0] || {};
    return state.notebooks.find(notebook=>notebook.id==state.curBookId);
  }
}
const mutations = {
  setNotebooks(state,{notebooks}){
    state.notebooks = notebooks
  },
  addNotebook(state,{notebook}){
    state.notebooks.unshift(notebook)
  },
  deleteNotebook(state,{notebookId}){
    state.notebooks = state.notebooks.filter(notebook=>notebook.id !==notebookId)
  },
  updateNotebook(state,{notebookId,title}){
    // 浅拷贝
    let notebook = state.notebooks.find(notebook=>notebook.id===notebookId);
    notebook.title = title;
  },
  setCurBookId(state,{notebookId}) {
    console.log(notebookId)
    state.curBookId = notebookId
  }
}
const actions = {
  getNotebooks({commit}){
    return Notebook.getAll().then(res=>{
      commit('setNotebooks',{notebooks:res.data});
    })
  },
  addNotebook({commit},{title}){
    return Notebook.addNotebook({title}).then(res=>{
      commit('addNotebook',{notebook:res.data})
    })
  },
  deleteNotebook({commit},{notebookId}){
    return Notebook.deleteNotebook(notebookId).then(res=>{
      commit('deleteNotebook',{notebookId})
      Message.success(res.msg)
    }).catch(res=>{
      Message.warning(res.msg)
    })
  },
  updateNotebook({commit},{notebookId,title}){
    return Notebook.updateNotebook(notebookId,{title}).then(res=>{
      commit('updateNotebook',{notebookId,title})
    })
  }

}

export default {
  state,
  getters,
  mutations,
  actions
}

notes

import Note from '@/apis/notes'
import {Message} from 'element-ui'
window.Note = Note;
const state = {
  notes: null,
  curNoteId:null
}
const getters = {
  notes: state=>state.notes || [],
  curNote: state=> {
    if(!Array.isArray(state.notes)) return {};
    // 假如没有传递参数,就获取第一个笔记
    if(!state.curNoteId) return state.notes[0] || {};
    return state.notes.find(note=>note.id==state.curNoteId) || {};
  }
}
const mutations = {
  setNotes(state,{notes}){
    state.notes = notes
  },
  setCurNoteId(state, { curnoteId }) {
    state.curNoteId = curnoteId;
  },
  addNotes(state,{note}){
    note.friendlyTime = '刚刚',
    note.updateFriendlyTime = '刚刚'
    state.notes.unshift(note)
  },
  deleteNote(state,{noteId}){

    state.notes = state.notes.filter(note=>note.id !==noteId) || {}
  },
  updateNote(state,{noteId,title,content}){
    // 浅拷贝
    let note = state.notes.find(note=>note.id===noteId);
    note.title = title;
    note.content = content;
  },

}
const actions = {
  getNotes({commit},{notebookId}){
    return Note.getAll({notebookId}).then(res=>{
      commit('setNotes',{notes:res.data});

    })
  },
  addNote({commit},{notebookId,title,content}){
    return new Promise((resolve,reject)=>{
      Note.addNote({notebookId},{title,content}).then(res=>{
        commit('addNotes',{note:res.data})
        Message.success('请在此处添加笔记内容')
        resolve(res.data)
      })
    })
  },
  deleteNote({commit},{noteId}){
    return Note.deleteNote({noteId}).then(res=>{
      commit('deleteNote',{noteId})
      Message.success(res.msg)
    }).catch(res=>{
      Message.warning(res.msg)
    })
  },
  updateNote({commit},{noteId,title,content}){
    return Note.updateNote({noteId,title,content}).then(res=>{
      commit('updateNote',{noteId,title,value})
    }).catch(()=>{})
  }

}

export default {
  state,
  getters,
  mutations,
  actions
}

trash
xxx

具体交互

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,699评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,124评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,127评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,342评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,356评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,057评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,654评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,572评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,205评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,343评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,015评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,704评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,196评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,690评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,348评论 2 358

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,245评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,744评论 2 59
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,983评论 3 119
  • 八秒钟爱情 “如果你只能拥有八秒的爱情你会做什么?” “我会选择做一条鱼,在前七秒完成相识、相知、相恋、相忘。就在...
    阿格雷先生阅读 517评论 0 1
  • 美国为了控制中国的崛起,厉害了的特朗普对中国芯片实行精准制裁,倾刻中国的第二互联网制造中兴厂家全面休克,但出乎意外...
    Wangyifang阅读 311评论 0 0