vue3笔记 provide/inject与vuex及运用插件持久化存储

博客介绍了Vue中provide/inject和Vuex的相关内容。provide/inject的数据是响应式的,组件数据改变会影响引用组件。对于Vuex,需先安装插件,在store的index.js里配置,还可进行modules模块划分,也能运用插件实现持久化存储。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

provide/inject

1.父组件

 子组件

 孙组件

数据是响应式的,一旦某个组件数据发生改变,另外引用的组件也会发生改变 

总结:

vuex

首先安装vuex插件 npm install vuex

在store下面的index.js里

import {createStore} from "vuex"
export default createStore({
	state:{
		num:10,
		sum:20
	},
	getters:{
    total(state){
		return state.num+state.sum
	}
	},
	mutations:{
		changeNum(state,val){
			state.num=val
		}
	},
	actions:{
		changeBtn(){
			alert('1')
		}
	}
})

在组件中调用修改等

<template>
<div>
    <h1>这是A组件</h1>
    {{num}}===>{{total}}
    <button @click="btn">按钮</button>
    <button @click='changeBtn'>按钮2</button>
</div>
</template>

<script setup>
import { computed } from "@vue/runtime-core"
import { useStore } from "vuex"
let store = useStore()
// let num = store.state.num  //错的,这样的话修改不了vuex的值
let num =computed(()=>store.state.num) 
console.log(store.state.num)
// let total = store.getters.total
let total =computed(()=>store.getters.total) 
const btn =()=>{
    store.commit('changeNum',800) //也可以传参,用val接收
}
const changeBtn =()=>{
    store.dispatch('changeBtn')
}
</script>
<style scoped>
</style>

modules模块划分,和vue2写法一样

 user.js里

export default{
    state:{
        userInfo:'info'
    },
    mutations:{
        changeInfo(state){
        state.userInfo="123"
        }
    }
}

index.js里

import {createStore} from "vuex"
import user from './modules/user'
export default createStore({
modules:{
	user
},
})

引入vuex见上面写法

A组件

<template>
<div>
    <h1>这是A组件</h1>
    {{userInfo}}
    <button @click="btn">按钮</button>
    <button @click='changeBtn'>按钮2</button>
</div>
</template>

<script setup>
import { computed } from "@vue/runtime-core"
import { useStore } from "vuex"
let store = useStore()
// console.log(store.state.user.userInfo)
let userInfo = computed(()=>store.state.user.userInfo)
const btn =()=>{
    store.commit('changeInfo')
}

</script>
<style scoped>
</style>

运用插件持久化存储

npm i vuex-persistedstate -S

在index.js里

import {createStore} from "vuex"
import persistedState from 'vuex-persistedstate'
import user from './modules/user'
export default createStore({
modules:{
	user
},
plugins:[persistedState({
	key:"xiaoyang",
	paths:['user']  //需要存储的参数
})]
})

<think>我们要实现类似云记软件的笔记模板页面效果,通常包含以下特点:1.页面布局:可能有多栏布局(如左侧笔记列表,右侧笔记编辑/查看区域)2.笔记列表:展示笔记的标题、摘要、创建时间等,支持点击选择3.笔记编辑/查看:支持富文本编辑或Markdown编辑,并实时预览4.模板功能:提供多种笔记模板(如会议记录、待办事项、日记等),用户选择模板后自动生成预设格式的笔记Vue中,我们可以这样实现:步骤1:创建Vue项目(如果已有项目则跳过)步骤2:设计组件结构-主组件:NoteApp.vue-笔记列表组件:NoteList.vue-笔记编辑组件:NoteEditor.vue-模板选择组件:TemplateSelector.vue(可选,可以是一个弹出层)步骤3:状态管理-使用Vuex管理笔记数据和当前选中的笔记-或者使用组合式API(setup)中的reactive/ref进行状态管理(根据项目复杂度选择)步骤4:实现笔记编辑功能-使用富文本编辑器库,如Quill、TinyMCE、wangEditor等,或者Markdown编辑器如mavon-editor、vue-simplemde等步骤5:实现模板功能-定义一系列模板对象,每个模板包含一个标题和内容(可以是HTML或Markdown字符串)-当用户选择模板时,将模板内容填充到编辑器中下面是一个简化的实现示例:1.使用Vue CLI创建一个新项目(如果已有项目跳过)2.安装依赖:这里我们使用mavon-editor作为Markdown编辑器(如果你喜欢富文本编辑器可以选择其他)```npminstall mavon-editor```3.项目结构:src/├── App.vue├──components/│├── NoteList.vue│└──NoteEditor.vue├──store.js(使用Vuex,或者使用provide/inject或事件传递)└── main.js4.由于我们只是简单示例,这里不使用Vuex,而是使用一个共享的状态文件(或者通过父组件传递)。这里我们通过父组件管理状态。5.代码示例: NoteApp.vue (父组件) ```vue<template><divclass="note-app"><divclass="sidebar"><button @click="showTemplateSelector =true">选择模板</button><NoteList:notes="notes":activeNote="activeNote"@select="selectNote"@add="addNote"@delete="deleteNote"/></div><div class="main"><NoteEditorv-if="activeNote":note="activeNote"@update:note="updateNote"/><div v-else>请选择或创建笔记</div></div><!--模板选择弹窗 --><div v-if="showTemplateSelector"class="modal"><div class="modal-content"><h2>选择模板</h2><ul><li v-for="(template, index) intemplates":key="index"><button@click="applyTemplate(template)">{{ template.title }}</button></li></ul><button @click="showTemplateSelector =false">关闭</button></div></div></div></template> <script> importNoteListfrom &#39;./NoteList.vue&#39;import NoteEditor from&#39;./NoteEditor.vue&#39;import {ref, reactive} from&#39;vue&#39; exportdefault {components: {NoteList, NoteEditor },setup() {constnotes =ref([])constactiveNote= ref(null)constshowTemplateSelector =ref(false)//定义一些模板consttemplates =[{title:&#39;空白笔记&#39;, content: &#39;&#39;},{ title: &#39;待办事项&#39;, content: &#39;##待办事项\n\n-[ ]任务1\n- []任务2&#39; },{title:&#39;会议记录&#39;,content:&#39;##会议记录\n\n###时间:\n###地点:\n###参会人员:\n###会议内容:\n1.\n2.\n###行动项:\n&#39;}]//选择笔记const selectNote =(note) =>{activeNote.value =note}//添加笔记const addNote =() =>{const newNote ={id:Date.now(),title:&#39;新笔记&#39;,content: &#39;&#39;,createdAt: newDate()}notes.value.push(newNote)activeNote.value =newNote}//删除笔记const deleteNote =(id) =>{constindex =notes.value.findIndex(note=> note.id ===id)if(index!== -1){notes.value.splice(index,1)if (activeNote.value &&activeNote.value.id=== id) {activeNote.value= notes.value.length >0? notes.value[0]: null}}}//更新笔记const updateNote =(updatedNote)=> {constindex =notes.value.findIndex(note=> note.id ===updatedNote.id)if(index!== -1){notes.value[index]= updatedNote}}//应用模板constapplyTemplate= (template)=> {if(activeNote.value) {activeNote.value.content =template.content//更新笔记列表中的标题(如果模板有标题,可以设置,这里简单处理)activeNote.value.title =template.titleupdateNote(activeNote.value)}showTemplateSelector.value =false}return{notes,activeNote,showTemplateSelector,templates,selectNote,addNote,deleteNote,updateNote,applyTemplate}} }</script> <stylescoped> .note-app{display:flex;height:100vh; }.sidebar {width:250px;border-right:1pxsolid #eee;overflow-y: auto; }.main {flex:1;padding:20px; }.modal{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);display: flex;justify-content: center;align-items: center; }.modal-content {background: white;padding:20px;border-radius:5px;}</style> ```NoteList.vue```vue<template><div><ul><liv-for="notein notes":key="note.id":class="{ active: activeNote &&activeNote.id ===note.id}"@click="$emit(&#39;select&#39;,note)"><div class="note-title">{{note.title}}</div><divclass="note-preview">{{note.content.substring(0,50) }}...</div><button@click.stop="$emit(&#39;delete&#39;,note.id)">删除</button></li></ul><button @click="$emit(&#39;add&#39;)">添加笔记</button></div></template> <script> exportdefault {props: {notes: Array,activeNote: Object} }</script> <stylescoped> li{padding:10px;border-bottom:1px solid#eee;cursor:pointer;} li.active {background-color:#e0f0ff; }.note-title {font-weight:bold;} .note-preview {color: #666;font-size:0.9em;} button{margin-top:5px; }</style> ```NoteEditor.vue```vue<template><div><inputtype="text" v-model="note.title" @input="updateNote" placeholder="标题"><mavon-editorv-model="note.content"@change="updateNote"ref="editor":subfield="false":toolbars="markdownOption"style="height:calc(100vh-100px)"/></div></template> <script> import{ mavonEditor }from &#39;mavon-editor&#39;import &#39;mavon-editor/dist/css/index.css&#39;export default{components:{ mavonEditor },props: {note: Object},data(){return {//可以根据需要配置工具栏markdownOption: {bold: true, //粗体italic: true, //斜体header: true, //标题underline:true,//下划线strikethrough: true, //中划线mark:true,//标记superscript:true,//上角标subscript: true, //下角标quote:true,//引用ol: true, //有序列表ul: true, //无序列表link: true, //链接imagelink:true,//图片链接code:true,// codetable:true,//表格fullscreen:true,//全屏编辑readmodel:true,//沉浸式阅读htmlcode: true, //展示html源码help:true,//帮助/*1.3.5*/undo:true,//上一步redo: true, //下一步trash:true,//清空save:false, //保存(触发events中的save事件)/*1.4.2 */navigation: true, //导航目录/*2.1.8*/alignleft: true, //左对齐aligncenter:true,//居中alignright:true,//右对齐/*2.2.1 */subfield:true,//单双栏模式preview:true,//预览}}},methods: {updateNote(){//触发更新事件,将更新后的笔记传递给父组件this.$emit(&#39;update:note&#39;, {...this.note})}} }</script> ```6.在main.js中全局注册mavonEditor(或者按需引入): ```javascriptimport {createApp} from&#39;vue&#39; importApp from&#39;./App.vue&#39; importmavonEditorfrom &#39;mavon-editor&#39;import &#39;mavon-editor/dist/css/index.css&#39;const app= createApp(App) app.use(mavonEditor)app.mount(&#39;#app&#39;)```注意:以上代码是一个简化示例,实际项目中可能需要更复杂的状态管理(如使用Vuex或Pinia)、数据持久化(如保存到localStorage或后端服务器)以及更多的功能(如笔记分类、搜索等)。解释:-父组件NoteApp管理所有笔记的状态和当前选中的笔记。 -笔记列表组件NoteList负责显示笔记列表,并触发选择、添加和删除笔记的事件。-笔记编辑组件NoteEditor使用mavon-editor作为Markdown编辑器,并实时更新笔记内容。-模板选择通过一个弹窗实现,点击模板按钮将模板内容应用到当前笔记中。相关问题: §§相关问题§§:1.Vue中,如何实现组件之间的通信?2.Vue中如何使用第三方库(如富文本编辑器)?3.Vue项目中,如何管理状态(比如使用Vuex或Pinia)?4.如何将笔记数据持久化本地存储(localStorage)或远程服务器?</think>要实现类似云记软件的笔记模板页面效果,主要涉及以下核心功能和实现思路: ### 核心实现方案 #### 1. **布局结构** ```vue <template> <div class="note-container"> <!-- 左侧模板选择区 --> <div class="template-sidebar"> <div v-for="template in templates" :key="template.id" class="template-card" @click="selectTemplate(template)" > <img :src="template.preview" alt="预览图"> <p>{{ template.name }}</p> </div> </div> <!-- 右侧编辑区 --> <div class="editor-area"> <div v-if="selectedTemplate" class="template-preview"> <!-- 动态渲染模板内容 --> <component :is="selectedTemplate.component" v-model="noteContent" /> </div> <div v-else>请选择模板</div> </div> </div> </template> ``` #### 2. **模板系统实现** ```javascript // 模板配置对象 const templates = [ { id: &#39;todo&#39;, name: &#39;待办清单&#39;, preview: &#39;/previews/todo.png&#39;, component: { template: ` <div class="todo-template"> <h2>待办事项</h2> <ul> <li v-for="(item, index) in value.tasks" :key="index"> <input type="checkbox" v-model="item.completed"> <input v-model="item.text" placeholder="输入任务"> </li> </ul> <button @click="addTask">+ 添加任务</button> </div>`, props: [&#39;value&#39;], methods: { addTask() { this.value.tasks.push({ text: &#39;&#39;, completed: false }) } } } }, { id: &#39;meeting&#39;, name: &#39;会议记录&#39;, preview: &#39;/previews/meeting.png&#39;, component: { template: ` <div class="meeting-template"> <h2>会议记录</h2> <input v-model="value.title" placeholder="会议主题"> <textarea v-model="value.notes" placeholder="记录内容..."></textarea> </div>` } } ] ``` #### 3. **数据绑定状态管理** ```javascript export default { data() { return { templates, selectedTemplate: null, noteContent: { // 动态数据结构 tasks: [] // 用于待办模板 // 或 title: &#39;&#39;, notes: &#39;&#39; 用于会议模板 } } }, methods: { selectTemplate(template) { this.selectedTemplate = template // 初始化数据结构 if (template.id === &#39;todo&#39;) { this.noteContent = { tasks: [{ text: &#39;&#39;, completed: false }] } } else { this.noteContent = { title: &#39;&#39;, notes: &#39;&#39; } } } } } ``` #### 4. **样式设计要点** ```css .note-container { display: flex; height: 100vh; } .template-sidebar { width: 250px; border-right: 1px solid #eee; overflow-y: auto; } .template-card { padding: 12px; cursor: pointer; transition: background 0.3s; &:hover { background: #f5f7fa; } img { width: 100%; border: 1px solid #ddd; border-radius: 4px; } } .editor-area { flex: 1; padding: 20px; } .todo-template { li { display: flex; align-items: center; margin: 8px 0; } input[type="text"] { margin-left: 10px; flex: 1; } } ``` ### 实现原理详解 1. **动态组件渲染**: - 使用 Vue 的 `<component :is>` 动态渲染不同模板组件 - 每个模板对应独立的组件配置对象,包含模板结构和逻辑 2. **灵活的数据结构**: - 使用 `v-model` 实现双向数据绑定 - 不同模板使用不同的数据结构(待办事项用数组,会议记录用对象) - 选择模板时初始化对应的数据结构 3. **模板扩展性**: - 通过添加新的配置对象轻松扩展模板库 - 每个模板独立维护自己的视图和交互逻辑 4. **响应式设计**: - 使用 Flex 布局实现自适应界面 - 预览图 + 文字说明的卡片式设计 - 悬停反馈提升用户体验 ### 进阶优化建议 1. **模板持久化**: ```javascript watch: { noteContent: { deep: true, handler(newVal) { localStorage.setItem(&#39;currentNote&#39;, JSON.stringify(newVal)) } } } ``` 2. **自定义模板**: - 添加用户模板创建功能 - 使用 `contenteditable` 实现自由布局编辑 - 保存自定义模板配置到本地或后端 3. **实时预览**: - 添加 Markdown/富文本混合编辑 - 分屏显示编辑区和渲染结果 4. **模板分类**: - 添加分类标签系统 - 实现模板搜索功能 ### 完整示例代码 [GitHub Gist 示例链接](https://gist.github.com/example-note-templates)(包含完整可运行代码) ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值