• vuex入门


    背景:小型应用里的每个组件维护着自有的状态,即当前应用的状态的一部分,所以整个应用的状态被分散在了各个角落,但是我们经常遇到要把
    状态的一部分
    共享给多个组件的情况。
    状态其实可以形象地想成我们的 data 里面的各个属性。
    Vuex 使用了单状态树(single state tree),一个 store 对象就存储了整个应用层的状态。它让我们可以更方便地定位某一具体的状态,并且在调试时能简单地获取到当前整个应用的快照。
    先埋个伏笔。Vuex 使用的这种 single state tree 与 modularity 模块化是不冲突的,问题是,如何将 state 与 mutation 分到子模块中?
    要使用 store ,首先必须
    Vue.use(Vuex)
    ,然后将 store
    const store = new Vuex.store()
    inject 定义到 Vue 实例 app 中
    new Vue({store})
    ,实现从根组件注入到所有子组件中,接着就可以在子组件中使用
    this.$store
    当一个组件需要使用多个某 store 的状态属性或 getters ,可以使用 shared helper ---- 共享帮手
    ,它会返回一个对象 。
    it('helper: mapState (object)', () =& {
    conststore =newVuex.Store({
    getters: {
    constvm =newVue({
    computed: mapState({
    // 在 mapState 里面我们既可以调用 store 的 state ,也可以调用 store 的 getters
    a: (state, getters) =&{
    returnstate.a + getters.b
    expect(vm.a).toBe(3)
    store.state.a++
    expect(vm.a).toBe(4)
    那么如何将它与本地的计算属性结合使用呢?一般我们会使用一个工具,将多个对象合而为一,再把这个最终的对象传递给 computed。但是这里我们可以直接使用 es6 的 stage 3 的 object spread operator ---- 对象扩展操作符,来超简洁地实现这一功能。
    computed: {
    localComputed () {}
    // 将其中的属性与本地的计算属性合并在一起
    ...mapState({
    message:state=&state.obj.message
    有时候我们需要从 store 的状态派生出其他状态,然后对这个状态(的方法)在多个组件中加以利用。通常我们的做法是复制这个方法,或者将它封装为一个公用的方法,然后在需要的时候导入,但是两者其实都不甚理想。Vuex 提供了 getters 属性,用途类似 stores 中的计算属性。
    getters 中的方法接受两个参数,分别为 state 以及 getters(其他 getters),用法如下。
    getters: {
    doneTodosCount: (state, getters) =&{
    returngetters.doneTodos.length
    那么我们在其他组件内部使用 getters 也变得十分简单
    computed: {
    doneTodosCount () {
    returnthis.$store.getters.doneTodosCount
    mapGetters
    可以将 store 的 getters 映射到本地的计算属性中来,除了可以使用数组之外,还可以使用对象起别名。
    ...mapGetters([
    'doneTodosCount',
    'anotherGetter',
    能改变 Vuex store 中的 state 状态的唯一方法是提交 mutation 变更。mutation 和事件很像:都有字符串类型的 type 以及 handler 句柄。我们在 handler 中实际修改 state,state 为每个 mutation 的第一个参数。
    conststore =newVuex.Store({
    mutations: {
    increment (state) {
    // mutate state
    state.count++
    // call, 只有在使用 type increment 调用 mutation 时才能称为 mit('increment')
    commit 的第二个可选参数为 payload 有效载荷,可以为普通类型或对象类型等等。
    commit 方法还可以通过对象形式调用,这种情况下,这个对象都会被当成 payload 。
    type:'increment',
    little tips
    建议使用大写命名 Mutation
    将所有大写变量存放在一个文件中,需要的时候引入。使用 es6 的计算属性名新特性来使用常量作为方法名。
    // mutation-types.js
    exportconstSOME_MUTATION ='SOME_MUTATION'
    // store.js
    importVuexfrom'vuex'
    import{ SOME_MUTATION }from'./mutation-types'
    conststore =newVuex.Store({
    state: { ... },
    mutations: {
    // we can use the ES2015 computed property name feature
    // to use a constant as the function name
    [SOME_MUTATION] (state) {
    // mutate state
    es6 计算属性名
    // e.g: 使用含有空格的变量作为属性名会报错,此时可以将它存为字符串或者存在中括号包裹的变量中
    varlastName ="last name";
    varperson = {
    "first name":"Nicholas",
    // 中括号包裹的变量
    [lastName]: "Zakas"
    console.log(person["last name"]);// Zakas
    mutations 必须都是同步的,它的改变必须在调用之后立即执行
    因为它是唯一可以修改 state 的,如果它使用了异步方法,将会使我们的 state 变得无法追踪,定位问题也变得是否困难
    在组件中 commit mutation 时
    可以使用 this.$mit() 或者使用 mapMutations 方法,后者可以将组件中的方法映射到 mit 调用(需要在根组件注入 store)。
    import{ mapMutations }from'vuex'
    exportdefault{
    methods: {
    // 传入数组
    ...mapMutations([
    'increment'// map this.increment() to this.$mit('increment')
    // 传入对象,可以使用 alias
    ...mapMutations({
    add:'increment'// map this.add() to this.$mit('increment')
    actions 是提交 mutations 的,它可以有任意的异步操作。
    actions 的第一个参数是 context,它向外暴露一组与 store 实例相同的方法/属性,所以可以直接调用 mit 或者访问 context.state 或者 context.getters 。我们通常使用 es6 的参数解构来简化我们的代码,直接写成
    { commit }
    actions: {
    increment ({ commit }) {
    commit('increment')
    如何触发 Actions?
    actions 通过
    store.dispatch('actionName')
    触发,其方法体中再触发 mutation,但是 mutations 是可以直接通过 mit 触发的,那么为什么不直接使用 mit(‘mutationName’) 呢?因为,actions 是可以异步执行的,而 mutations 只可以同步。所以这种 dispatch 调用可以在 action 内执行异步操作,也就是说可以执行异步 mutation。
    可以使用 payload 格式或者对象形式触发。二者等价
    // dispatch with a payload
    store.dispatch('incrementAsync', {
    // dispatch with an object
    store.dispatch({
    type:'incrementAsync',
    shopping cart 中的实际应用,既调用了异步 API,又提交了多个 mutation。
    actions: {
    checkout ({ commit, state }, payload) {
    // save the items currently in the cart
    constsavedCartItems = [...state.cart.added]
    // send out checkout request, and optimistically
    // clear the cart
    commit(types.CHECKOUT_REQUEST)
    // the 异步 shop API accepts a success callback and a failure callback
    shop.buyProducts(
    // handle success
    () =& commit(types.CHECKOUT_SUCCESS),
    // handle failure
    () =& commit(types.CHECKOUT_FAILURE, savedCartItems)
    在组件中分发 Actions
    this.$store.dispatch()
    mapActions
    映射组件方法到
    store.dispatch
    中调用(需要注入 root)。同
    mapMutations
    Actions 组合,怎么控制 actions 执行呢?
    由于 actions 是异步的,因此我们就很难知道一个 action 什么时候完成,以及该怎么把多个 action 组合起来,处理复杂的异步工作流?
    store.dispatch()
    方法返回了我们定义的 action handler 的返回值,所以我们可以直接返回一个 Promise 呀~
    actions: {
    actionA ({ commit }) {
    returnnewPromise((resolve, reject) =&{
    setTimeout(()=&{
    commit('someMutation')
    可以这么用
    store.dispatch('actionA').then(()=&{
    然后在另一个 action 中
    actions: {
    actionB ({ dispatch, commit }) {
    returndispatch('actionA').then(()=&{
    commit('someOtherMutation')
    由于 Vuex 使用了单状态树,所以随着我们应用的规模逐渐增大, store 也越来越膨胀。为了应对这个问题,Vuex 允许我们将 store 分成多个 modules。每个 module 有着自己的 state, mutations, actions, getters, 甚至可以有嵌套( nested )的 modules。比如说:
    constmoduleA = {
    state: { ... },
    mutations: { ... },
    actions: { ... },
    getters: { ... }
    constmoduleB = {
    state: { ... },
    mutations: { ... },
    actions: { ... }
    conststore =newVuex.Store({
    modules: {
    a: moduleA,
    b: moduleB
    // 注意,调用的时候,多个模块都在 state 对象中,而非 modules 中
    store.state.a // -& moduleA's state
    store.state.b // -& moduleB's state
    modules 中的各种 state , local or root?
    mutations 和 getters 中,接受的第一个参数是 modules 的本地 state
    constmoduleA = {
    state: {count:0},
    mutations: {
    increment: (state) {
    // state is the local module state
    state.count++
    getters: {
    doubleCount (state) {
    returnstate.count *2
    相似地,在 actions 中,
    context.state
    为本地 state,而
    context.rootState
    为根 state
    constmoduleA = {
    actions: {
    incrementIfOdd ({ state, commit }) {
    if(state.count %2===1) {
    commit('increment')
    getters 的第三个参数才是 root state
    constmoduleA = {
    getters: {
    sumWithRootCount (state, getters, rootState) {
    returnstate.count + rootState.count
    Strict Mode & Form Handling
    严格模式下,如果在 mutation handler 之外修改了 Vuex 的 state,应用就会抛错。比如我们将 Vuex 中的某个数据,用 Vue 的 v-model 绑定到 input 时,一旦感应到 input 改动,就会尝试去直接修改这个数据,严格模式下就会报错。所以建议是绑定 value 值,然后在 input 时调用 action 。
    &input:value="message"@input="updateMessage"&
    computed: {
    ...mapState({
    message:state=&state.obj.message
    methods: {
    updateMessage (e) {
    this.$mit('updateMessage', e.target.value)
    mutation 可以这么处理
    mutations: {
    updateMessage (state, message) {
    state.obj.message = message
    诚然,这样做是很仔细明了的,但是我们也不能用 v-model 这么好用的方法了,另外一个方法就是继续使用 v-model ,并配套使用 双向计算属性和 setter 。
    computed: {
    message: {
    returnthis.$store.state.obj.message
    set (value) {
    // 直接 commit 到 mutation,type 为 updateMessage
    this.$mit('updateMessage', value)
    建议部署到开发环境的时候一定一定要关掉严格模式。
    已发表评论数()
    请填写推刊名
    描述不能大于100个字符!
    权限设置: 公开
    仅自己可见
    正文不准确
    标题不准确
    排版有问题
    主题不准确
    没有分页内容
    图片无法显示
    视频无法显示
    与原文不一致如何使用Vuex+Vue.js构建单页应用
    作者:懂懂懂懂懂懂懂涛大人
    字体:[ ] 类型:转载 时间:
    这篇文章主要教大家如何使用Vuex+Vue.js构建单页应用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章。感觉收获挺多,自己在它的例子的基础上进行了一些优化和自定义功能,在这里和大家分享下学习心得。
    在这篇教程中我们将通过构建一个笔记应用来学习如何在我们的 Vue 项目中使用 Vuex。我们将大概的过一遍什么是 Vuex.js,在项目中什么时候使用它,和如何构建我们的 Vue 应用。
    这里放一张我们项目的预览图片:
    项目源码:;有需要的同学可以直接下载源码查看。
    主要知识点
    状态管理机制的使用
    的基础 api
    脚手架的安装及使用
    的语法,这里推荐看下阮一峰的入门教程
    在我们迫不及待的开始项目之前,我们最好先花几分钟来了解下 Vuex 的核心概念。
    Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和 Redux 的设计思想,但简化了概念,并且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。
    state 这样概念初次接触的时候可能会感觉到有点模糊,简单来说就是将 state 看成我们项目中使用的数据的集合。然后,Vuex 使得 组件本地状态(component local state)和 应用层级状态(application state) 有了一定的差异。
    component local state:该状态表示仅仅在组件内部使用的状态,有点类似通过配置选项传入 Vue 组件内部的意思。
    application level state:应用层级状态,表示同时被多个组件共享的状态层级。
    假设有这样一个场景:我们有一个父组件,同时包含两个子组件。父组件可以很容易的通过使用 props 属性来向子组件传递数据。
    但是问题来了,当我们的两个子组件如何和对方互相通信的? 或者子组件如何传递数据给他父组件的?在我们的项目很小的时候,这个两个问题都不会太难,因为我们可以通过事件派发和监听来完成父组件和子组件的通信。
    然而,随着我们项目的增长:
    1、保持对所有的事件追踪将变得很困难。到底哪个事件是哪个组件派发的,哪个组件该监听哪个事件?
    2、项目逻辑分散在各个组件当中,很容易导致逻辑的混乱,不利于我们项目的维护。
    3、父组件将变得和子组件耦合越来越严重,因为它需要明确的派发和监听子组件的某些事件。
    这就是 Vuex 用来解决的问题。 Vuex 的四个核心概念分别是:
    The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
    Getters:用来从 store 获取 Vue 组件数据。
    Mutators:事件处理器用来驱动状态的变化。
    Actions:可以给组件使用的函数,以此用来驱动事件处理器 mutations
    如何你暂时还不太理解这个四个概念,不用着急,我们将在后面的项目实战中详细的解释。
    下面这张图详细的解释了 Vuex 应用中数据的流向(Vuex 官方图)
    简单解释下:
    Vuex 规定,属于应用层级的状态只能通过 Mutation 中的方法来修改,而派发 Mutation 中的事件只能通过 action。
    从左到又,从组件出发,组件中调用 action,在 action 这一层级我们可以和后台数据交互,比如获取初始化的数据源,或者中间数据的过滤等。然后在 action 中去派发 Mutation。Mutation 去触发状态的改变,状态的改变,将触发视图的更新。
    数据流都是单向的
    组件能够调用 action
    action 用来派发 Mutation
    只有 mutation 可以改变状态
    store 是响应式的,无论 state 什么时候更新,组件都将同步更新
    这个应用将使用 webpack 来做模块打包,处理和热重启。使用 Vue 官方提供的脚手架 vue-cli。
    安装 vue-cli
    npm install -g vue-cli
    注:Node.js &= 4.x, 5.x 最好
    初始化应用
    vue init webpack vue-notes-app
    cd vue-notes-app
    npm install // 安装依赖包
    npm run dev // 启动服务
    初始化一个项目名为vue-notes-app的应用,并选择使用 webpack 打包方式。在命令行中按照提示选择初始化配置项。其中在选择 JSLint 校验的时候,推荐选择 AirBNB 规范。
    使用你最喜欢的编辑器打开我们刚刚新建的项目,项目的结构大概如下图:
    components/ 文件夹用来存放我们的 Vue 组件
    vuex/ 文件夹存放的是和 Vuex store 相关的东西(state object,actions,mutators)
    build/ 文件是 webpack 的打包编译配置文件
    config/ 文件夹存放的是一些配置项,比如我们服务器访问的端口配置等
    dist/ 该文件夹一开始是不存在,在我们的项目经过 build 之后才会产出
    App.vue 根组件,所有的子组件都将在这里被引用
    index.html 整个项目的入口文件,将会引用我们的根组件 App.vue
    main.js 入口文件的 js 逻辑,在 webpack 打包之后将被注入到 index.html 中
    新增笔记,新增一篇笔记,编辑区显示空的笔记内容
    删除笔记,删除一篇笔记之后,编辑区域显示当前笔记类别的第一项
    笔记列表切换,分为全部笔记和收藏笔记两种,在切换之后,编辑区域显示当前列表的第一条笔记
    收藏笔记,给当前激活的笔记打上收藏的标签
    项目组件划分
    在这个项目中,我们将总共使用四个组件:根组件 App.vue,操作栏组件 Toolbar.vue,别表组件 NotesList.vue,笔记编辑组件 Editor.vue。
    创建 Vuex Store
    按照上面我们列出来的功能模块,我们在 Vuex/ 下面建立一个 store.js 文件。
    import Vue from 'vue';
    import Vuex from 'vuex';
    Vue.use(Vuex);
    // 需要维护的状态
    const state = {
    notes: [],
    activeNote: {},
    const mutations = {
    // 初始化 state
    INIT_STORE(state, data) {
    state.notes = data.notes,
    state.show = data.
    state.activeNote = data.activeN
    // 新增笔记
    NEW_NOTE(state) {
    var newNote = {
    id: +new Date(),
    title: '',
    content: '',
    favorite: false
    state.notes.push(newNote);
    state.activeNote = newN
    // 修改笔记
    EDIT_NOTE(state, note) {
    state.activeNote =
    // 修改原始数据
    for (var i = 0; i & state.notes. i++) {
    if(state.notes[i].id === note.id){
    state.notes[i] =
    // 删除笔记
    DELETE_NOTE(state) {
    state.notes.$remove(state.activeNote);
    state.activeNote = state.notes[0] || {};
    // 切换笔记的收藏与取消收藏
    TOGGLE_FAVORITE(state) {
    state.activeNote.favorite = !state.activeNote.
    // 切换显示数据列表类型:全部 or 收藏
    SET_SHOW_ALL(state, show){
    state.show =
    // 切换数据展示,需要同步更新 activeNote
    if(show === 'favorite'){
    state.activeNote = state.notes.filter(note =& note.favorite)[0] || {};
    state.activeNote = state.notes[0] || {};
    // 设置当前激活的笔记
    SET_ACTIVE_NOTE(state, note) {
    state.activeNote =
    export default new Vuex.Store({
    创建 Vuex Actions
    在 Vuex/ 下面建立一个 action.js,用来给组件使用的函数。
    function makeAction(type) {
    return ({ dispatch }, ...args) =& dispatch(type, ...args);
    const initNote = {
    id: +new Date(),
    title: '我的笔记',
    content: '第一篇笔记内容',
    favorite: false
    // 模拟初始化数据
    const initData = {
    show: 'all',
    notes: [initNote],
    activeNote: initNote
    export const initStore = ({ dispatch }) =& {
    dispatch('INIT_STORE', initData);
    // 更新当前activeNote对象
    export const updateActiveNote = makeAction('SET_ACTIVE_NOTE');
    // 添加一个note对象
    export const newNote = makeAction('NEW_NOTE');
    // 删除一个note对象
    export const deleteNote = makeAction('DELETE_NOTE');
    export const toggleFavorite = makeAction('TOGGLE_FAVORITE');
    export const editNote = makeAction('EDIT_NOTE');
    // 更新列表展示
    export const updateShow = makeAction('SET_SHOW_ALL');
    创建 Vuex Getters
    在 vuex/ 下面建立一个 getter.js 文件,用来从 store 获取数据。
    // 获取 noteList,这里将会根据 state.show 的状态做数据过滤
    export const filteredNotes = (state) =& {
    if(state.show === 'all'){
    return state.notes || {};
    }else if(state.show === 'favorite'){
    return state.notes.filter(note =& note.favorite) || {};
    // 获取列表展示状态 : all or favorite
    export const show = (state) =& {
    return state.
    // 获取当前激活 note
    export const activeNote = (state) =& {
    return state.activeN
    以上就是我们 Vuex 的所有逻辑了,在定下了我们需要完成的功能之后,接下来就是只需要在组件中去调用 action 来实现对应的功能了。
    在这里我们将使用 vue-router 来做路由,引用 bootstrap 样式。
    index.html
    &!DOCTYPE html&
    &meta charset="utf-8"&
    &title&vuex-notes-app&/title&
    &link rel="stylesheet" href="/bootstrap/3.3.6/css/bootstrap.min.css"&
    &div id="app"&&/div&
    &!-- built files will be auto injected --&
    所有的入口逻辑我们都将在 main.js 中编写
    import Vue from 'vue';
    import App from './App';
    import VueRouter from 'vue-router';
    import VueResource from 'vue-resource';
    // 路由模块和HTTP模块
    Vue.use(VueResource);
    Vue.use(VueRouter);
    const router = new VueRouter();
    router.map({
    '/index': {
    component: App
    router.redirect({
    '*': '/index'
    router.start(App, '#app');
    根组件 App.vue
    &template&
    &div id="app" class="app"&
    &toolbar&&/toolbar&
    &notes-list&&/notes-list&
    &editor&&/editor&
    &/template&
    html, #app {
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    height: 100%;
    max-height: 100%;
    import Toolbar from './components/Toolbar';
    import NotesList from './components/NotesList';
    import Editor from './components/Editor';
    import store from './vuex/store';
    import { initStore } from './vuex/actions';
    export default {
    components: {
    NotesList,
    actions: {
    this.initStore()
    在根组件中引用了三个子组件:Toolbar.vue, NotesList.vue, Editor.vue。
    注意:我们在配置里面加入了 vuex 这么一个选项,这里用来将我们 action 里面定义的方法给暴露出来,我们在根组件中只做了一件事情,那就是初始化模拟数据,因此我们在组件生命周期的 ready 阶段调用了 actions 里面的 initStore 来初始化我们的 store 里面的 state
    Toolbar.vue
    &template&
    &div id="toolbar"&
    &i class="glyphicon logo"&&img src="../assets/logo.png" width="30" height="30"&&/i&
    &i @click="newNote" class="glyphicon glyphicon-plus"&&/i&
    &i @click="toggleFavorite" class="glyphicon glyphicon-star" :class="{starred: activeNote.favorite}"&&/i&
    &i @click="deleteNote" class="glyphicon glyphicon-remove"&&/i&
    &/template&
    import { newNote, deleteNote, toggleFavorite } from '../vuex/actions';
    import { activeNote } from '../vuex/getters';
    export default {
    getters: {
    activeNote
    actions: {
    deleteNote,
    toggleFavorite
    &style lang="scss" scoped&
    height: 100%;

    color: #767676;
    padding: 35px 25px 25px 25
    .starred {
    color: #F7AE4F;
    font-size: 30
    margin-bottom: 35
    opacity: 0.8;
    transition: opacity 0.5
    opacity: 1;
    在这里,我们用到了 Vuex 的一个案例就是我们需要知道当前的激活的笔记是否是收藏类别的,如果是,我们需要高亮收藏按钮,那么如何知道呢?那就是通过 vuex 里面的 getters 获取当前激活的笔记对象,判断它的 favorite 是否为 true。
    始终牢记一个概念,vuex 中数据是单向的,只能从 store 获取,而我们这个例子中的 activeNote 也是始终都在 store.js 中维护的,这样子就可以给其他组件公用了
    // 需要维护的状态
    const state = {
    notes: [],
    activeNote: {},
    NotesList.vue
    &template&
    &div id="notes-list"&
    &div id="list-header"&
    &h2&Notes | &/h2&
    &div class="btn-group btn-group-justified" role="group"&
    &!-- all --&
    &div class="btn-group" role="group"&
    &button type="button" class="btn btn-default"
    @click="toggleShow('all')"
    :class="{active: show === 'all'}"&All Notes&/button&
    &!-- favorites --&
    &div class="btn-group" role="group"&
    &button type="button" class="btn btn-default"
    @click="toggleShow('favorite')"
    :class="{active: show === 'favorite'}"&Favorites&/button&
    &!-- 渲染笔记列表 --&
    &div class="container"&
    &div class="list-group"&
    &a v-for="note in filteredNotes"
    class="list-group-item" href="#"
    :class="{active: activeNote === note}"
    @click="updateActiveNote(note)"&
    &h4 class="list-group-item-heading"&
    {{note.title.trim().substring(0,30)}}
    &/template&
    import { updateActiveNote, updateShow } from '../vuex/actions';
    import { show, filteredNotes, activeNote } from '../vuex/getters';
    export default {
    getters: {
    filteredNotes,
    activeNote
    actions: {
    updateActiveNote,
    updateShow
    methods: {
    toggleShow(show) {
    this.updateShow(show);
    笔记列表组件,主要有三个操作
    切换渲染笔记
    点击列表 title,切换 activeNote
    我们通过 getters 中的 filteredNotes 方法获取笔记列表
    // 获取 noteList,这里将会根据 state.show 的状态做数据过滤
    export const filteredNotes = (state) =& {
    if(state.show === 'all'){
    return state.notes || {};
    }else if(state.show === 'favorite'){
    return state.notes.filter(note =& note.favorite) || {};
    可以看到,我们获取的列表是依赖于 state.show 这个状态的。而我们的切换列表操作恰好就是调用 actions 里面的方法来更新 state.show,这样一来,实现了数据列表的动态刷新,而且我们对树的操作都是通过调用 actions 的方法来实现的。
    我们再看,在切换列表的时候,我们还需要动态的更新 activeNote。看看我们在 store.js 中是如何做的:
    // 切换显示数据列表类型:全部 or 收藏
    SET_SHOW_ALL(state, show){
    state.show =
    // 切换数据展示,需要同步更新 activeNote
    if(show === 'favorite'){
    state.activeNote = state.notes.filter(note =& note.favorite)[0] || {};
    state.activeNote = state.notes[0] || {};
    触发这些操作的是我们给两个按钮分别绑定了我们自定义的函数,通过给函数传入不同的参数,然后调用 actions 里面的方法,来实现对数据的过滤,更新。
    Editor.vue
    &template&
    &div id="note-editor"&
    &div class="form-group"&
    &input type="text" name="title"
    class="title form-control"
    placeholder="请输入标题"
    @input="updateNote"
    v-model="currentNote.title"&
    v-model="currentNote.content" name="content"
    class="form-control" row="3" placeholder="请输入正文"
    @input="updateNote"&&/textarea&
    &/template&
    import { editNote } from '../vuex/actions';
    import { activeNote } from '../vuex/getters';
    export default {
    getters: {
    activeNote
    actions: {
    computed: {
    // 通过计算属性得到的一个对象,这样子我们就能愉快的使用 v-model 了
    currentNote: activeNote
    methods: {
    // 为什么这么做? 因为在严格模式中不允许直接在模板层面去修改 state 中的值
    updateNote() {
    this.editNote(this.currentNote);
    在 Editor.vue 组件中,我们需要能够实时的更新当前的 activeNote 组件和列表中对应的我们正在修改的笔记对象的内容。
    由于我们前面提到过,在组件中是不允许直接修改 store.js在里面的状态值的,所以在这里的时候,我们通过一个计算属性,将 store 里面的状态值赋值给一个对象,然后在自定义的 updateNotes() 方法中,去调用 action,同时传入 currentNote 对象。
    在 store.js 中,我们是这么做的,找到对应的 id 的对象,重新赋值,因为前面提到过,我们的数据是响应式的,在这里进行了改变,对应的视图也将刷新改变,这样一来就实现了实时编辑,实时渲染的功能了。
    // 修改笔记
    EDIT_NOTE(state, note) {
    state.activeNote =
    // 修改原始数据
    for (var i = 0; i & state.notes. i++) {
    if(state.notes[i].id === note.id){
    state.notes[i] =
    在这个项目中,我们并没有引入 vue-resource 插件,只是自己模拟了部分的数据,有兴趣的同学可以自己去试试。

  • 相关阅读:
    马拉车算法
    E. You 题解(思维)
    马拉车练习2
    The Boomsday Project 题解(玄学dp)
    Journey to Un'Goro 题解(思维+剪枝搜索)
    Black and white 题解(思维+prim)
    Rise in Price 题解(dp+随机数据)
    高斯消元
    马拉车练习1
    概率期望问题
  • 原文地址:https://www.cnblogs.com/frx666/p/6744428.html
Copyright © 2020-2023  润新知