Browse Source

improvement: 增加store中在某个节点后插入新节点(同时更新焦点)、修改节点内容、解析md语法来改变节点属性为标题等特性

ChenYangfan 6 years ago
parent
commit
3050fbc245

+ 44 - 12
src/components/EditableItem.vue

@@ -1,28 +1,36 @@
 <template>
 <template>
   <section>
   <section>
-    <div
+    <component
+      ref="element"
+      :is="tagName"
       contenteditable
       contenteditable
       @keydown.stop="handleKeyDown"
       @keydown.stop="handleKeyDown"
-      :v-html="innerContent"
-    ></div>
-    输入的内容为:{{ innerContent }}
+      @input="checkBlockType"
+    >
+    </component>
+    输入的内容为:{{ content }}
   </section>
   </section>
 </template>
 </template>
 
 
 <script>
 <script>
-import { CREATE_ITEM_AFTER } from '../store/types/editor-types'
+import {
+  CREATE_ITEM_AFTER,
+  SET_TAG_NAME,
+  CHANGE_CONTENT
+} from '../store/types/editor-types.js'
+import blockTypeRegs from '@/utils/block-type-regs.js'
 export default {
 export default {
   name: 'editable-item',
   name: 'editable-item',
-  props: ['id', 'tagName', 'content'],
+  props: ['id', 'tagName', 'content', 'isFocus'],
   data: function() {
   data: function() {
-    return {
-      innerContent: this.content
-    }
+    return {}
+  },
+  mounted() {
+    this.$refs.element.innerHTML = this.content
+    this.isFocus ? this.$refs.element.focus() : this.$refs.element.blur()
   },
   },
   methods: {
   methods: {
     handleKeyDown(e) {
     handleKeyDown(e) {
-      console.log(e.key)
-
       switch (e.key) {
       switch (e.key) {
         case 'Enter':
         case 'Enter':
           e.preventDefault()
           e.preventDefault()
@@ -31,10 +39,34 @@ export default {
 
 
         default:
         default:
           requestAnimationFrame(() => {
           requestAnimationFrame(() => {
-            this.innerContent = e.target.innerText
+            this.$store.commit(CHANGE_CONTENT, {
+              id: this.id,
+              content: e.target.innerText
+            })
           })
           })
           break
           break
       }
       }
+    },
+    checkBlockType(e) {
+      this.tagName === 'div' &&
+        Object.entries(blockTypeRegs)
+          .map(array => ({ tagName: array[0], reg: array[1] }))
+          .some(({ tagName, reg }) => {
+            if (reg.test(this.content)) {
+              this.$store.commit(SET_TAG_NAME, {
+                id: this.id,
+                tagName: tagName
+              })
+              this.$store.commit(CHANGE_CONTENT, {
+                id: this.id,
+                content: this.content.replace(reg, '')
+              })
+            }
+          })
+    },
+    changeTagName(newTagName) {
+      this.tagName !== newTagName &&
+        this.$store.commit(SET_TAG_NAME, { id: this.id, tagName: newTagName })
     }
     }
   }
   }
 }
 }

+ 33 - 6
src/store/modules/editor.js

@@ -1,24 +1,51 @@
 import {
 import {
-  CREATE_ITEM_AFTER
+  CREATE_ITEM_AFTER,
+  SET_TAG_NAME,
+  CHANGE_CONTENT
 } from '../types/editor-types'
 } from '../types/editor-types'
 import uuid from 'uuid'
 import uuid from 'uuid'
 
 
 export default {
 export default {
-  namespace: true,
   state: {
   state: {
     editableItems: [{
     editableItems: [{
       id: uuid.v4(),
       id: uuid.v4(),
       tagName: 'div',
       tagName: 'div',
-      content: '2'
+      content: '2',
+      isFocus: true
     }]
     }]
   },
   },
   mutations: {
   mutations: {
     [CREATE_ITEM_AFTER](state, payload) {
     [CREATE_ITEM_AFTER](state, payload) {
-      state.editableItems = [...state.editableItems, {
+      // todo 快要看不懂了...需要改一改
+      const index = state.editableItems.indexOf(state.editableItems.filter(item => item.id === payload.id)[0])
+      state.editableItems = [...state.editableItems.slice(0, index + 1).map(item => ({
+        ...item,
+        isFocus: false
+      })), {
         id: uuid.v4(),
         id: uuid.v4(),
         tagName: 'div',
         tagName: 'div',
-        content: '2'
-      }]
+        content: '',
+        isFocus: true
+      }, ...state.editableItems.slice(index + 1).map(item => ({
+        ...item,
+        isFocus: false
+      }))]
+    },
+    [SET_TAG_NAME](state, payload) {
+      state.editableItems = [...state.editableItems.map(item =>
+        item.id === payload.id ? {
+          ...item,
+          tagName: payload.tagName
+        } : item
+      )]
+    },
+    [CHANGE_CONTENT](state, payload) {
+      state.editableItems = [...state.editableItems.map(item =>
+        item.id === payload.id ? {
+          ...item,
+          content: payload.content
+        } : item
+      )]
     }
     }
   },
   },
   actions: {},
   actions: {},

+ 2 - 0
src/store/types/editor-types.js

@@ -1,3 +1,5 @@
 export const INIT_BY_SPECIFIC_ITEMS = 'initBySpecialItems'
 export const INIT_BY_SPECIFIC_ITEMS = 'initBySpecialItems'
 export const CREATE_ITEM_AFTER = 'createItemAfter'
 export const CREATE_ITEM_AFTER = 'createItemAfter'
 export const REMOVE_ITEM_BEFORE = 'removeItemBefore'
 export const REMOVE_ITEM_BEFORE = 'removeItemBefore'
+export const SET_TAG_NAME = 'setTagName'
+export const CHANGE_CONTENT = 'changeContent'

+ 26 - 0
src/utils/block-type-regs.js

@@ -0,0 +1,26 @@
+/**
+ * todo 正则完全不熟,先放着到时候仍然需要检验写得对不对
+ */
+
+const blockTypeRegs = {}
+
+blockTypeRegs.h1 = new RegExp(/^#\s/)
+// blockTypeRegs.h2 = new RegExp(/^##\s/)
+// blockTypeRegs.h3 = new RegExp(/^###\s/)
+// blockTypeRegs.h4 = new RegExp(/^####\s/)
+// blockTypeRegs.h5 = new RegExp(/^#####\s/)
+// blockTypeRegs.h6 = new RegExp(/^######\s/)
+
+// blockTypeRegs.blockquote = new RegExp(/^>\s/)
+
+// blockTypeRegs.hr = new RegExp(/---/)
+
+// blockTypeRegs.slideBreakReg = new RegExp(/----/)
+
+// blockTypeRegs.pre = new RegExp(/^```([\\s\\S]*?)```$/)
+
+// blockTypeRegs.ulItemReg = new RegExp(/^[\\s]-\s/)
+
+// blockTypeRegs.olItemReg = new RegExp(/^[\\s][0-9]+\s/)
+
+export default blockTypeRegs

+ 1 - 0
src/views/editor/Editor.vue

@@ -6,6 +6,7 @@
         :id="item.id"
         :id="item.id"
         :tagName="item.tagName"
         :tagName="item.tagName"
         :content="item.content"
         :content="item.content"
+        :isFocus="item.isFocus"
       />
       />
     </template>
     </template>
   </section>
   </section>