vue学习-1.md

  • 视图层:vue(html+css+js)
  • 网络通信:axios
  • 页面跳转:vue-router
  • 状态管理:vuex

javascript:原生JS,是按照ECMAScript(简称 ES)标准的开发方式,特点是所有浏览器都支持
- TypeScript:微软的标准。是javascript的i一个超集。运行完它之后会打包将其变成javascript(类似sass编译运行完成css一样)

JavaScript 框架

  • jQuery
  • Angular:模块化
  • React:虚拟DOM(把很多DOM操作放到内存中去做,不用走浏览器,快)
  • Vue:模块化+虚拟DOM
  • Axios:前端通信框架。因为vue 的边界明确,就是为了处理DOM,所以并不具备通信能力,此时就需要一个特定的通信框架和服务器交互

javascript 构建工具

  • babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如用于编译TypeScript
  • webpack:模块打包器,主要作用是打包,压缩,合并和按序加载

Node.js:方便前端人员开发后台应用的技术。其框架和项目管理工具如下:

  • Express:Node.js框架
  • Koa:Node.js简化版
  • NPM:项目综合管理工具
  • YARN:NPM的替代方案

Web2.0时代:Ajax出来之后网页可以但页面应用了,因为页面不用刷新不用跳转了

大前端:前端为主的MV*

  • MVC(同步通信为主):Model,View,Controller
  • MVP(异步通信为主):Model,View,Presenter
  • MVVM(异步通信为主):Model(JS),View(HTML操作的元素),ViewModel(连接视图和工具的中间层。Vue)

axios 异步通信

vuex

基本使用-1 state

demo1

state 是存储需要用的数据

  • src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        products: [
          {name: "aaa", price: 10},
          {name: "bbb", price: 20},
          {name: "ccc", price: 30},
          {name: "ddd", price: 40},
          {name: "eee", price: 50}
        ]
      },
      mutations: {
      },
      actions: {
      },
      modules: {
      }
    })
    
  • src/main.js

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    Vue.config.productionTip = false
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
    
  • src/components/test1.vue

    <template>
      <div class="hello">
        <ul v-for="item in products" :key="item.id">
          <li>{{item.name}}</li>
          <li>{{item.price}}</li>
        </ul>
      </div>
    </template>
    <script>
    export default {
      name: "test1",
      props: {
        msg: String
      },
      computed: {
        products(){
          return this.$store.state.products;
        }
      }
    };
    </script>
    <style scoped lang="scss">
    ul>li{
      list-style-type: none;
    }
    </style>
    
demo2

和基本使用-1里面的store.js、main.js一样,只是改变了vue文件,让price字段的值变为它的一半

<template>
  <div>
    <ul v-for="item in saleProduct" :key="item.id">
      <li>{{item.name}}</li>
      <li>{{item.price}}</li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  computed: {
    saleProduct() {
      var products = this.$store.state.products.map(item => {
        return {
          name: "hello~ " + item.name,
          price: item.price / 2
        };
      });
      return products;
    }
  }
};
</script>
<style lang="scss" scoped>
ul>li{
  list-style-type: none;
}
</style>

基本使用-3 getters

getters 是获取需要的数据

  • store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        products: [
          {name: "aaa", price: 10},
          {name: "bbb", price: 20},
          {name: "ccc", price: 30},
          {name: "ddd", price: 40},
          {name: "eee", price: 50}
        ]
      },
      getters: {
        saleProducts: (state) => {
          var products = state.products.map(item => {
            return {
              name: "hello~ " + item.name,
              price: item.price / 2
            };
          });
          return products;
        }
      },
      mutations: {
      },
      actions: {
      },
      modules: {
      }
    })
    
  • test3.vue

    <template>
      <div>
        <ul v-for="item in saleProducts" :key="item.id">
          <li>{{item.name}}</li>
          <li>{{item.price}}</li>
        </ul>
      </div>
    </template>
    
    <script>
      export default {
        computed: {
          saleProducts() {
            return this.$store.getters.saleProducts;
          }
        },
      }
    </script>
    <style lang="scss" scoped>
    ul>li{
      list-style-type: none;
    }
    </style>
    

基本使用-4 mutations

mutations 是当你触发事件去改变数据时使用

这块要实现的功能是:点击按钮之后对应的price会降价

demo1 一般写法
<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.price}}</li>
    </ul>
    <button @click="reduce">reduce price</button>
  </div>
</template>

<script>
  export default {
    computed: {
      saleProducts(){
        return this.$store.getters.saleProducts;
      }
    },
    methods: {
      reduce() {
        this.$store.state.products.forEach(item => {
          item.price -= 1;
        })
      }
    },
  }
</script>

<style lang="scss" scoped>

</style>

点击按钮之前的初始状态

点击按钮之后的降价状态(这里降了0.5而不是1,是因为调用的是this.$store.getters.saleProducts;里面的price,它是按照之前的方式展示,有除以2)

demo2 通过mutations来写
  • src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    products: [
      { name: "aaa", price: 10 },
      { name: "bbb", price: 20 },
      { name: "ccc", price: 30 },
      { name: "ddd", price: 40 },
      { name: "eee", price: 50 }
    ]
  },
  getters: {
    saleProducts: (state) => {
      var products = state.products.map(item => {
        return {
          name: "hello~ " + item.name,
          price: item.price / 2
        };
      });
      return products;
    }
  },
  mutations: {
    reducrProducts: state => {
      state.products.forEach(item => {
        item.price -= 1;
      })
    }
  },
  actions: {},
  modules: {}
})
  • test4.vue
<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.price}}</li>
    </ul>
    <button @click="reduce">reduce price</button>
  </div>
</template>

<script>
export default {
  computed: {
    saleProducts() {
      return this.$store.getters.saleProducts;
    }
  },
  methods: {
    reduce() {
      // this.$store.state.products.forEach(item => {
      //   item.price -= 1;
      // })
      this.$store.commit("reducrProducts");
    }
  }
};
</script>

<style lang="scss" scoped>
</style>

这块出来的效果和上面的一样

基本使用-4 actions

actions 与 mutations 类似,不同在于:

  • actions 提交的是 mutation,而不是直接变更状态
  • actions 可以包含任意异步操作

这里要实现的就是点击 reduce price 降价按钮,在3秒钟之后显示降价后的price

demo1 直接在mutation中写
  • src/store/index.js

给之前的reducePrice中加一个 setTimeOut 定时器

  mutations: {
    reducrProducts: state => {
      setTimeout(() => {
        state.products.forEach(item => {
          item.price -= 1;
        })
      }, 3000);
    }
  },

然后点击reduce price 降价按钮,可以实现3秒钟之后降价

demo2 通过actions 结合 mutations 来实现
  • src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    products: [{
        name: "aaa",
        price: 10
      },
      {
        name: "bbb",
        price: 20
      },
      {
        name: "ccc",
        price: 30
      },
      {
        name: "ddd",
        price: 40
      },
      {
        name: "eee",
        price: 50
      }
    ]
  },
  getters: {
    saleProducts: (state) => {
      var products = state.products.map(item => {
        return {
          name: "hello~ " + item.name,
          price: item.price / 2
        };
      });
      return products;
    }
  },
  mutations: {
    reduceProducts: state => {
      // setTimeout(() => {
      state.products.forEach(item => {
        item.price -= 1;
      })
      // }, 3000);
    }
  },
  actions: {
    reduceProducts: (context) => {
      setTimeout(() => {
        context.commit("reduceProducts")
      }, 3000);
    }
  },
  modules: {}
})
  • test5.vue
<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.price}}</li>
    </ul>
    <button @click="reduce">reduce price</button>
  </div>
</template>
<script>
export default {
  computed: {
    saleProducts() {
      return this.$store.getters.saleProducts;
    }
  },
  methods: {
    reduce() {
      // 这是调用$store里面的mutations中的方法
      // this.$store.commit("reduceProducts");

      // 这是调用$store里面的actions中的方法
      this.$store.dispatch("reduceProducts");
    }
  }
};
</script>
<style lang="scss" scoped>
</style>

现在的实现效果就和上面的一样了

demo3 通过vue页面传参

比如现在商品降价不让它降价1了,而是降一个自己传递过去的价格

  • test5.vue
<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.price}}</li>
    </ul>
    <button @click="reduce(5)">reduce price</button>
  </div>
</template>
<script>
export default {
  computed: {
    saleProducts() {
      return this.$store.getters.saleProducts;
    }
  },
  methods: {
    reduce(amount) {
      // 这是调用$store里面的mutations中的方法
      // this.$store.commit("reduceProducts");

      // 这是调用$store里面的actions中的方法
      this.$store.dispatch("reduceProducts", amount);
    }
  }
};
</script>
<style lang="scss" scoped>
</style>
  • src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    products: [{
        name: "aaa",
        price: 10
      },
      {
        name: "bbb",
        price: 20
      },
      {
        name: "ccc",
        price: 30
      },
      {
        name: "ddd",
        price: 40
      },
      {
        name: "eee",
        price: 50
      }
    ]
  },
  getters: {
    saleProducts: (state) => {
      var products = state.products.map(item => {
        return {
          name: "hello~ " + item.name,
          price: item.price / 2
        };
      });
      return products;
    }
  },
  mutations: {
    reduceProducts: (state, disploy) => {
      // setTimeout(() => {
      state.products.forEach(item => {
        item.price -= disploy;
      })
      // }, 3000);
    }
  },
  actions: {
    reduceProducts: (context, disploy) => {
      setTimeout(() => {
        context.commit("reduceProducts", disploy)
      }, 3000);
    }
  },
  modules: {}
})

mapGetters 辅助函数

mapgetters 辅助函数仅仅是将store中的getters 映射到局部计算属性

看一下之前的getters相关写法:

  • src/store/index.js
  getters: {
    saleProducts: (state) => {
      var products = state.products.map(item => {
        return {
          name: "hello~ " + item.name,
          price: item.price / 2
        };
      });
      return products;
    }
  }
  • test5.vue
  computed: {
    saleProducts() {
      return this.$store.getters.saleProducts;
    }
  },

结合代码来说明一下:上面的这段代码是之前的例子中用到的,它的getters 中只有一个 saleProducts 方法,想在vue页面中用的话,就需要在 computed 通过this.$store.getters.xxx进行调用。那么如果在getters中有很多类似saleProducts 的方法的话,按照之前的做法就是需要在vue页面的 computed 通过this.$store.getters.xxx 一个一个进行调用。这样写很麻烦。。所以就有了mapgetters辅助函数

demo1 使用 mapGetters
  • src/store/index.js 这个文件内容不变
  • test6.vue
<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.name}}</li>
      <li>{{item.price}}</li>
    </ul>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  computed: {
    // saleProducts() {
    //   return this.$store.getters.saleProducts;
    // }
    ...mapGetters([
      "saleProducts",

	  // 如果你想给saleProducts变个名字的话,可以像下面一样做
	  // product: "saleProducts",
    ])
  }
};
</script>
<style lang="scss" scoped>
ul > li {
  list-style-type: none;
}
</style>

出来的效果和之前通过this.$store.getters.saleProducts一样

mapActions 辅助函数

mapActions 的用法基本和 mapGetters 的用法一样,在methods中直接用就行了

<template>
  <div>
    <ul v-for="item in saleProducts" :key="item.id">
      <li>{{item.name}}</li>
      <li>{{item.price}}</li>
    </ul>
    <button @click="reduce(5)">reduce price</button>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";
export default {
  computed: {
    // saleProducts() {
    //   return this.$store.getters.saleProducts;
    // }
    ...mapGetters(["saleProducts"])
  },
  methods: {
    ...mapActions({
    // 这里的 reduce 对应上面 button 方法中的 reduce
      reduce: "reduceProducts"
    })
  }
};
</script>
<style lang="scss" scoped>
ul > li {
  list-style-type: none;
}
</style>

module

直接将state/getters/mutations/actions分隔出去

  • src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        products: [
          { name: "aaa", price: 10 },
          { name: "bbb", price: 20 },
          { name: "ccc", price: 30 },
          { name: "ddd", price: 40 },
          { name: "eee", price: 50 }
        ]
      },
      getters: {
        saleProducts: (state) => {
          var products = state.products.map(item => {
            return {
              name: "hello~ " + item.name,
              price: item.price / 2
            };
          });
          return products;
        }
      },
      mutations: {
        reduceProducts: (state, disploy) => {
          state.products.forEach(item => {
            item.price -= disploy;
          })
        }
      },
      actions: {
        reduceProducts: (context, disploy) => {
          setTimeout(() => {
            context.commit("reduceProducts", disploy)
          }, 3000);
        }
      },
      modules: {}
    })
    

上面的代码中,state/getters/mutations/actions 都是写在一起的。也可以将它们分开写在不同的js文件,然后引入到上面的index.js文件👇

  • index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    import state from './state'
    import getters from './getters'
    import mutations from './mutations'
    import actions from './actions'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state,
      getters,
      mutations,
      actions,
      modules: {}
    })
    
  • src/store/state.js

    export default {
      products: [
        { name: "aaa", price: 10 },
        { name: "bbb", price: 20 },
        { name: "ccc", price: 30 },
        { name: "ddd", price: 40 },
        { name: "eee", price: 50 }
      ]
    }
    
  • src/store/getters.js

    export default {
      saleProducts: (state) => {
        var products = state.products.map(item => {
          return {
            name: "hello~ " + item.name,
            price: item.price / 2
          };
        });
        return products;
      }
    }
    

上面这样分隔之后,也可以达到之前的效果。下面就开始分模块来写~

modules的应用

  • src/store/partA.js

    export default {
      state: {
        productNum: 100
      },
      getters: {
        brief: function (state) {
          return state.productNum + "个商品"
        }
      },
      mutations: {
        addProNum(state) {
          state.productNum++
        }
      },
      actions: {
        changeProNum(context) {
          setTimeout(() => {
            context.commit("addProNum")
          }, 2000);
        }
      }
    }
    
  • src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    import state from './state'
    import getters from './getters'
    import mutations from './mutations'
    import actions from './actions'
    import partA from './partA'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state,
      getters,
      mutations,
      actions,
      modules: {
        partA
      }
    })
    
  • test7.vue

    <template>
      <div>
        测试 modules
        <!-- 下面这两句效果一样 -->
        <h3>{{$store.state.partA.productNum}}</h3>
        <h3>{{partA.productNum}}</h3>
        <!-- 下面是getters -->
        <h3>{{brief}}</h3>
        <!-- 下面是mutations -->
        <button @click="addProNum">test mutations</button>
        <!-- 下面是actions -->
        <button @click="changeProNum">test actions</button>
      </div>
    </template>
    <script>
    import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
    let mapStateObj = mapState(["partA"]);
    let mapGettersObj = mapGetters(["brief"]);
    let mapMutationsObj = mapMutations(["addProNum"]);
    let mapActionsObj = mapActions(["changeProNum"]);
    export default {
      computed: {
        // 对mapStateObj进行解构
        ...mapStateObj,
        ...mapGettersObj
      },
      mounted() {
        console.log(this);
      },
      methods: {
        ...mapMutationsObj,
        ...mapActionsObj
      }
    };
    </script>
    <style lang="scss" scoped>
    </style>
    

这是默认情况下的界面展示

这是点击了test mutations按钮之后的界面展示。可以看到控制台中有出现mutation对应的内容

下面这张图是点击了test actions按钮之后的界面展示

命名空间 namespaced

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名

  • src/store/pardB.js

    export default {
      namespaced: true,
      state: {
        age: 15
      },
      getters: {
        info: function (state) {
          return state.age + "岁"
        }
      },
      mutations: {
        addAge(state) {
          state.age++
        }
      },
      actions: {
        changeAge(context) {
          setTimeout(() => {
            context.commit("addAge")
          }, 2000);
        }
      }
    }
    
  • test8.vue

    <template>
      <div>
        modules namespaced test
        <h3>{{partB.age}}</h3>
        <h3>{{info}}</h3>
    
        <button @click="addAge">mutation test</button>
        <button @click="changeAge">actions test</button>
      </div>
    </template>
    
    <script>
    import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
    let mapStateObj = mapState(["partB"]);
    let mapGettersObj = mapGetters('partB', ['info']);
    let mapMutationsObj = mapMutations('partB', ['addAge']);
    let mapActionsObj = mapActions('partB', ['changeAge'])
    
    export default {
      mounted() {},
      computed: {
        ...mapStateObj,
    
        // 下面的这三种写法出来的效果都是一样的
        ...mapGettersObj,
        // ...mapGetters('partB', [ 'info' ]),
        // ...mapGetters({ info: "partB/info" })
      },
      methods: {
        ...mapMutationsObj,
        // ...mapMutations('partB', ['addAge']),
        // ...mapMutations({ addAge: "partB/addAge" }),
    
        ...mapActionsObj,
        // ...mapActions('partB', ['changeAge'])
        // ...mapActions({ changeAge: "partB/changeAge" })
        
      }
    };
    </script>
    
    <style lang="scss" scoped>
    </style>
    

当然,除了上面的这些写法之外,还有一种

通过使用 createNamespacedHelpers 创建基于某个命名空间辅助函数。它返回一个对象,对象里有新的绑定在给定命名空间值上的组件绑定辅助函数

  • test8.vue

    <template>
      <div>
        modules namespaced createNamespacedHelpers test
        <h3>{{age}}</h3>
        <h3>{{info}}</h3>
        <button @click="addAge">mutations test</button>
        <button @click="changeAge">actions test</button>
      </div>
    </template>
    
    <script>
    import { createNamespacedHelpers } from "vuex";
    const { mapState, mapGetters, mapMutations, mapActions } = createNamespacedHelpers('partB')
    export default {
      computed: {
        ...mapState({ age: state => state.age }),
        ...mapGetters([ 'info' ])
      },
      methods: {
        ...mapMutations([ 'addAge' ]),
        ...mapActions([ 'changeAge' ])
      }
    };
    </script>
    
    <style lang="scss" scoped>
    </style>
    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值