毕设:week10-vue.js:Demo2(个人博客)----02添加多条笔记-重命名(下拉菜单--删除-收藏功能)

一、前言

上次完善了笔记的输入于显示功能,本次将在原来的基础上添加多条笔记-重命名(下拉菜单–删除-收藏功能)

二、项目代码

1.index.html

<html>
<head>
  <title>我的驿站</title>
  <!-- Icons & Stylesheets -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="style.css" />
</head>
<body>
<h1 style="text-align: center; font-size: 50px;">我的驿站</h1><hr>
  <!-- Include the library in the page -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/marked"></script>
  <script src="https://unpkg.com/moment"></script>

  <!-- Notebook app -->
  <div id="notebook">

    <!-- Sidebar -->
    <aside class="side-bar">
      <div class="toolbar">
        <button @click="addNote" :title="notes.length + ' note(s) already'"><i class="material-icons">add</i> 添加笔记</button>
      </div>
      <div class="notes">
        <div class="note" v-for="note of sortedNotes" :class="{selected: note === selectedNote}" @click="selectNote(note)"><i class="icon material-icons" v-if="note.favorite">star</i>{{note.title}}</div>
      </div>
    </aside>

    <template v-if="selectedNote">

      <!-- Main pane -->
      <section class="main">
        <div class="toolbar">
          <input v-model="selectedNote.title" placeholder="Note title" />

          <button @click="favoriteNote" title="收藏笔记"><i class="material-icons">{{ selectedNote.favorite ? 'star' : 'star_border' }}</i></button>

          <button @click="removeNote" title="删除笔记"><i class="material-icons">delete</i></button>
        </div>
        <textarea v-model="selectedNote.content"></textarea>
        <div class="toolbar status-bar">
          <span class="date">
            <span class="label">Created</span>
            <span class="value">{{ selectedNote.created | date }}</span>
          </span>
          <span class="lines">
            <span class="label">Lines</span>
            <span class="value">{{ linesCount }}</span>
          </span>
          <span class="words">
            <span class="label">Words</span>
            <span class="value">{{ wordsCount }}</span>
          </span>
          <span class="characters">
            <span class="label">Characters</span>
            <span class="value">{{ charactersCount }}</span>
          </span>
        </div>
      </section>

      <!-- Preview pane -->
      <aside class="preview" v-html="notePreview">
      </aside>

    </template>

  </div>

  <!-- Some JavaScript -->
  <script src="script.js"></script>
</body>
</html>

2.script.js

Vue.filter('date', time => moment(time).format('DD/MM/YY, HH:mm'))

// New VueJS instance
new Vue({
  name: 'notebook',

  // CSS selector of the root DOM element
  el: '#notebook',

  // Some data
  data () {
    return {
      // These are loaded from localStorage and have a default value
      // Don't forget the JSON parsing for the notes array
      notes: JSON.parse(localStorage.getItem('notes')) || [],
      selectedId: localStorage.getItem('selected-id') || null,
    }
  },

  // Computed properties
  computed: {
    selectedNote () {
      // We return the matching note with selectedId
      return this.notes.find(note => note.id === this.selectedId)
    },

    notePreview () {
      // Markdown rendered to HTML
      return this.selectedNote ? marked(this.selectedNote.content) : ''
    },

    sortedNotes () {
      return this.notes.slice().sort((a, b) => a.created - b.created)
      .sort((a, b) => (a.favorite === b.favorite)? 0 : a.favorite? -1 : 1)
    },

    linesCount () {
      if (this.selectedNote) {
        // Count the number of new line characters
        return this.selectedNote.content.split(/\r\n|\r|\n/).length
      }
    },

    wordsCount () {
      if (this.selectedNote) {
        var s = this.selectedNote.content
        // Turn new line cahracters into white-spaces
        s = s.replace(/\n/g, ' ')
        // Exclude start and end white-spaces
        s = s.replace(/(^\s*)|(\s*$)/gi, '')
        // Turn 2 or more duplicate white-spaces into 1
        s = s.replace(/[ ]{2,}/gi, ' ')
        // Return the number of spaces
        return s.split(' ').length
      }
    },

    charactersCount () {
      if (this.selectedNote) {
        return this.selectedNote.content.split('').length
      }
    },
  },

  // Change watchers
  watch: {
    // When our notes change, we save them
    notes: {
      // The method name
      handler: 'saveNotes',
      // We need this to watch each note's properties inside the array
      deep: true,
    },
    // Let's save the selection too
    selectedId (val, oldVal) {
      localStorage.setItem('selected-id', val)
    },
  },

  methods:{
    // Add a note with some default content and select it
    addNote () {
      const time = Date.now()
      // Default new note
      const note = {
        id: String(time),
        title: '我的笔记 ' + (this.notes.length + 1),
        content: '**我的驿站**从这里开始分享您德内心世界吧!',
        created: time,
        favorite: false,
      }
      // Add
      this.notes.push(note)
      // Select
      this.selectNote(note)
    },

    // Remove the selected note and select the next one
    removeNote () {
      if (this.selectedNote && confirm('是否确定删除该笔记?')) {
        // Remove the note in the notes array
        const index = this.notes.indexOf(this.selectedNote)
        if (index !== -1) {
          this.notes.splice(index, 1)
        }
      }
    },

    selectNote (note) {
      // This will update the 'selectedNote' computed property
      this.selectedId = note.id
    },

    saveNotes () {
      // Don't forget to stringify to JSON before storing
      localStorage.setItem('notes', JSON.stringify(this.notes))
      console.log('Notes saved!', new Date())
    },

    favoriteNote () {
      // this.selectedNote.favorite = !this.selectedNote.favorite
      // this.selectedNote.favorite = this.selectedNote.favorite ^ true
      this.selectedNote.favorite ^= true
    },
  },
})

3、style.css

body {
  font-family: sans-serif;
  font-size: 16px;
  height: 100%;
  margin: 0;
  box-sizing: border-box;
}

.material-icons {
  font-size: 24px;
  line-height: 1;
  vertical-align: middle;
  margin: -3px;
  padding-bottom: 1px;
}

#notebook > * {
  float: left;
  display: flex;
  flex-direction: column;
  height: 100%;

  > * {
    flex: auto 0 0;
  }
}

.side-bar {
  background: #f8f8f8;
  width: 20%;
  box-sizing: border-box;
}

.note {
  padding: 16px;
  cursor: pointer;
}

.note:hover {
  background: #ade2ca;
}

.note .icon {
  float: right;
}

button,
input,
textarea {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  box-sizing: border-box;
  outline: none !important;
}

button,
.note.selected {
  background: #40b883;
  color: white;
}

button {
  border-radius: 3px;
  border: none;
  display: inline-block;
  padding: 8px 12px;
  cursor: pointer;
}

button:hover {
  background: #63c89b;
}

input {
  border: solid 2px #ade2ca;
  border-radius: 3px;
  padding: 6px 10px;
  background: #f0f9f5;
  color: #666;
}

input:focus {
  border-color: #40b883;
  background: white;
  color: black;
}

button,
input {
  height: 34px;
}

.main, .preview {
  width: 40%;
}

.toolbar {
  padding: 4px;
  box-sizing: border-box;
}

.status-bar {
  color: #999;
  font-style: italic;
}

textarea {
  resize: none;
  border: none;
  box-sizing: border-box;
  margin: 0 4px;
  font-family: monospace;
}

textarea, .notes, .preview {
  flex: auto 1 1;
  overflow: auto;
}

.preview {
  padding: 12px;
  box-sizing: border-box;
  border-left: solid 4px #f8f8f8;
}

.preview p:first-child {
  margin-top: 0;
}

a {
  color: #40b883;
}

h1,
h2,
h3 {
  margin: 10px 0 4px;
  color: #40b883;
}

h1 {
  font-size: 2em;
}

h2 {
  font-size: 1.5em;
}

h3 {
  font-size: 1.2em;
}

h4 {
  font-size: 1.1em;
  font-weight: normal;
}

三、项目展示

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值