new Date()的月份是从0开始的。 javascript
下面表达式是:2018年6月1日 new Date(2018, 5, 1); 下面表达式是:2018年5月1日 new Date(2018, 4, 1); 或 new Date(2018, 5-1, 1); 下面表达式是:2018年5月31日(获得上个月的最后一天) new Date(2018, 5 , 0); 日的参数能够是0,也能够是负数,表示上个月底的那一天。 下面表达式是:2018年7月01日 new Date(2018, 5, 31);
l App.vue父组件:css
<template> <div> <MonthView :year="year" :month="month"></MonthView> </div> </template> <script> import MonthView from "./components/MonthView.vue"; export default { data(){ return { year : 2018 , month : 8 , } }, components : { MonthView }, methods : { } } </script>
l MonthView.vue子组件html
<template> <div> 月视图{{year}} {{month}} {{arr}} </div> </template> <script> export default { props : ["year" , "month"], computed : { arr(){ //计算日历的数组:三要素 //本月1号星期几 var this1DayWeek = new Date(this.year, this.month - 1, 1).getDay(); // 本月有几天 var thisMonthDay = new Date(this.year, this.month, 0).getDate(); // 上月有多少天 var prevMonthDay = new Date(this.year, this.month - 1, 0).getDate(); console.log(benyue1haoxingqiji) console.log(benyueyoujitian) console.log(shangyueduoshaotian) } } } </script>
l 显示在页面:前端
<template> <div> <table> <tr v-for="i in 6"> <td v-for="j in arr.slice((i-1) * 7, i * 7)"> {{j}} </td> </tr> </table> </div> </template> <script> export default { props:["year","month"], computed : { arr(){ var _arr = []; //存储42天的数组 // 计算日历的数组:三要素 //本月1号星期几,根据星期几获得上个月剩余天数 var this1DayWeek = new Date(this.year, this.month-1, 1).getDay(); //上个月有多少天 var prevMonthDay = new Date(this.year, this.month-1, 0).getDate(); //本月有几天 var thisMonthDay = new Date(this.year, this.month, 0).getDate(); //用本月1号星期几,推断出上月的剩余天数 for(var i = 0; i < this1DayWeek;i++){ _arr.unshift(prevMonthDay - i) } //循环本月天数(累加),从数组末尾插入 for(var i = 1; i <= thisMonthDay;i++){ _arr.push(i) } //补充下月的天数(满42天为止) var i = 1; while(_arr.length != 42){ _arr.push(i++); } return _arr; } } } </script>
l 显示农历,安装插件:vue
npm install solarlunar --save
<template> <div> <h1>月视图 {{year}}年{{month}}月</h1> <table> <tr> <th>日</th> <th>一</th> <th>二</th> <th>三</th> <th>四</th> <th>五</th> <th>六</th> </tr> <tr v-for="i in 6"> <td v-for="j in arr.slice((i-1) * 7, i * 7)"> <p class="p1">{{j.d}}</p> <p class="p2">{{j.n}}</p> </td> </tr> </table> </div> </template> <script> import solarLunar from 'solarLunar'; export default { props:["year","month"], computed : { arr(){ var _arr = []; //存储42天的数组 // 计算日历的数组:三要素 //本月1号星期几,根据星期几获得上个月剩余天数 var this1DayWeek = new Date(this.year, this.month-1, 1).getDay(); //上个月有多少天 var prevMonthDay = new Date(this.year, this.month-1, 0).getDate(); //本月有几天 var thisMonthDay = new Date(this.year, this.month, 0).getDate(); //用本月1号星期几,推断出上月的剩余天数 for(var i = 0; i < this1DayWeek;i++){ _arr.unshift({ d: prevMonthDay - i, n: solarLunar.solar2lunar(this.year, this.month-1, prevMonthDay - i).dayCn }) } //循环本月天数,累加,从数组末尾插入 for(var i = 1; i <= thisMonthDay;i++){ _arr.push({ d: i, n: solarLunar.solar2lunar(this.year, this.month, i).dayCn }) } //补充下个月的天数(满42天为止) var i = 1; while(_arr.length != 42){ _arr.push({ d : i, n : solarLunar.solar2lunar(this.year, this.month+1, i).dayCn }); i++; } console.log(_arr) return _arr; } } } </script>
下面作“换月换年”业务:java
App.vue父组件node
<template> <div> <MonthChooser :year="year" :month="month" :setYear="setYear" :setMonth="setMonth" > </MonthChooser> <MonthView :year="year" :month="month"></MonthView> </div> </template> <script> import MonthView from "./components/MonthView.vue"; import MonthChooser from "./components/MonthChooser.vue"; export default { data(){ return{ year :2018, month:8, } }, components :{ MonthView, MonthChooser }, methods : { setYear(year){ this.year = year; //设置年 }, setMonth(month){ this.month = month; //设置月 } } } </script>
MonthChooser.vue切换年月组件webpack
<template> <div> <h1> <button @click="goPrev()">-</button> <a href="###">{{year}}</a> 年{{month}}月 <button @click="goNext()">+</button> </h1> </div> </template> <script> export default { props:["year","month","setYear","setMonth"], methods :{ goNext(){ if(this.month < 12){ // 若是月份小于12,能够加月 this.setMonth(this.month + 1) }else{ // 不然就加年,而且重设下年为1月 this.setMonth(1) this.setYear(this.year + 1) } }, goPrev(){ if(this.month > 1){ // 若是月份大于1月,能够减月 this.setMonth(this.month - 1) }else{ // 不然就减年,而且重设上年为12月 this.setMonth(12); //重设为12月 this.setYear(this.year - 1); //减年 } } } } </script>
切换年代视图组件:git
l App.vue父组件github
<template> <div> <MonthChooser :year="year" :month="month" :setYear="setYear" :setMonth="setMonth" ></MonthChooser> <MonthView :year="year" :month="month"></MonthView> <DecadeView :year="year" :setYear="setYear"></DecadeView> </div> </template> <script> import MonthView from "./components/MonthView.vue"; import MonthChooser from "./components/MonthChooser.vue"; import DecadeView from "./components/DecadeView.vue"; export default { data(){ return { ... } }, components : { MonthView, MonthChooser, DecadeView }, methods : { ... } } </script>
l DecadeView.vue子组件
<template> <div> <table> <tr v-for="i in 10"> <!-- <td v-for="j in arr.slice((i-1) * 3, i * 3)"> --> <td v-for="j in 3" :class="{'cur':year == showYear(i, j)}" @click="setYear(showYear(i, j))" > {{showYear(i, j)}} </td> </tr> </table> </div> </template> <script> export default { props : ["year"], computed : { arr(){ var _arr = []; //计算年份的头 var tou = this.year - this.year % 10 - 10; //从获得的年份的头开始循环 + 30 for(var i = tou ; i < tou + 30;i++){ _arr.push(i); } return _arr; } }, methods : { showYear(i , j){ return this.arr[(j - 1) * 10 + (i - 1)] } } } </script> <style> .cur{color:red;font-weight:bold;} </style>
【如下开始完善整个项目】:
切换视图:App.vue父组件
<template> <div> <MonthChooser :year="year" :month="month" :setYear="setYear" :setMonth="setMonth" :setView="setView" v-if="view == 'month'" ></MonthChooser> <MonthView :year="year" :month="month" v-if="view == 'month'"></MonthView> <DecadeChooser :year="year" :month="month" :setYear="setYear" :setMonth="setMonth" :setView="setView" v-if="view=='decade'" ></DecadeChooser> <DecadeView :year="year" :setYear="setYear" v-if="view == 'decade'" :setView="setView" ></DecadeView> </div> </template> <script> import MonthView from "./components/MonthView.vue"; import MonthChooser from "./components/MonthChooser.vue"; import DecadeChooser from "./components/DecadeChooser.vue"; import DecadeView from "./components/DecadeView.vue"; export default { data(){ return { year : 2018 , month : 5 , view : "month" } }, components : { MonthView, MonthChooser, DecadeView, DecadeChooser }, methods : { ... setView(view){ this.view = view; //设置视图切换 } } } </script>
DecadeChooser.vue年视图按钮组件:
<template> <div> <h1> <button @click="goPrev()">-</button> {{year}}年<a href="javascript:;" @click="setView('month')">{{month}}月</a> <button @click="goNext()">+</button> </h1> </div> </template> <script> export default{ props : ["year", "month" , "setYear","setView"], methods : { goNext(){ this.setYear(this.year + 1) }, goPrev(){ if(this.year <= 1970) return; this.setYear(this.year - 1) } } } </script>
MonthChooser.vue月视图按钮组件:
<template> <div> <h1> <button @click="goPrev()">-</button> <a href="javascript:;" @click="setView('decade')">{{year}}</a>年{{month}}月 <button @click="goNext()">+</button> </h1> </div> </template> <script> export default{ props : ["year", "month" , "setYear", "setMonth","setView"], methods : { goNext(){ ... }, goPrev(){ ... } } } </script>
DecadeView.vue年份视图组件:
<template> <div> <table> <tr v-for="i in 10"> <td v-for="j in 3" :class="{'cur' : year == showYear(i , j)}" @click="tdClick(i,j)" > {{showYear(i , j)}} </td> </tr> </table> </div> </template> <script> export default { props : ["year","setYear","setView"], computed : { arr(){ ... } }, methods : { showYear(i , j){ return this.arr[(j - 1) * 10 + (i - 1)] }, tdClick(i , j){ this.setYear(this.showYear(i , j)); //切换年份 this.setView("month"); //切换年份后,回到月视图 } } } </script>
MonthView.vue月视图早已完善。
饿了么UI:http://element-cn.eleme.io/#/zh-CN
iviewUI :https://www.iviewui.com/
以饿了么UI为例
安装依赖:
npm install --save element-ui
在main.js中配置eleUI组件:
在引入 Element 时,能够传入一个全局配置对象。该对象目前仅支持 size 字段,用于改变组件的默认尺寸。按照引入 Element 的方式,具体操做以下:
import Vue from "vue"; import App from "./App.vue"; import ElementUI from 'element-ui'; //import 'element-ui/lib/theme-chalk/index.css'; //样式在index.html页面引入 // Vue.use(ElementUI); Vue.use(ElementUI, { size: 'small' }); new Vue({ el : "#app" , render: (h) => h(App) });
而后就能够在.vue组件中直接使用了。
npm install iview --save
如下是一个表示“单向数据流”理念的极简示意:
当咱们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
多个视图依赖于同一状态。
来自不一样视图的行为须要变动同一状态。
对于问题1:传参的方法对于多层嵌套的组件将会很是繁琐,而且对于兄弟组件间的状态传递无能为力。
对于问题2:咱们常常会采用父子组件直接引用或者经过事件来变动和同步状态的多份拷贝。以上的这些模式很是脆弱,一般会致使没法维护的代码。
所以,咱们为何不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,咱们的组件树构成了一个巨大的“视图”,无论在树的哪一个位置,任何组件都能获取状态或者触发行为!
另外,经过定义和隔离状态管理中的各类概念并强制遵照必定的规则,咱们的代码将会变得更结构化且易维护。
这就是 Vuex 背后的基本思想,借鉴了 Flux、Redux、和 The Elm Architecture。与其余模式不一样的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
以前咱们作的日历组件将数据放到了App.vue最大父组件上,而且还有:year、:month、:setYear、:setMonth等一系列的参数传递操做。
可是vuex就是将数据放到了全局store中。
不用vuex也能作项目,只不过数据管理起来很不方便。
官网:https://vuex.vuejs.org/zh-cn/
安装vuex:
npm install --save vuex
什么是vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单说:vuex就是一个状态管理容器,说白了就是将数据单独存放出去。
什么是“状态管理模式”?
每一个Vuex应用的核心就是store(仓库)。store就是一个容器,它包含着你项目中大部分的状态 (state)。
Vuex 和单纯的全局对象有如下两点不一样:
Vuex的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地获得高效更新变化。
你不能直接改变store中的状态。改变store中的状态的惟一途径就是经过commit提交mutation。这样使得咱们能够方便地跟踪每个状态的变化,从而让咱们可以实现一些工具帮助咱们更好地了解咱们的应用。
在main.js建立一个全局仓库(store),让咱们从一个简单的Vue计数器开始:
import Vue from 'vue'; import Vuex from 'vuex'; //引入Vuex包 import App from './App.vue'; Vue.use(Vuex); //将vuex安装到vue中 //建立一个仓库,而且存放一些全局数据(存放四大天王选项) const store = new Vuex.Store({ state : { a : 100 } }) new Vue({ el : "#app", store, //将store注入到全局中 render : (h)=> h(App) })
Vuex经过store选项,提供了一种机制将状态从根组件“注入”到每个子组件中(须要调用Vue.use(Vuex))
经过在根实例中注册store选项,该store实例会注入到根组件下的全部子组件中,而且组件能经过this.$store访问。
在App.vue中的生命周期中输出this,能看到vue实例化对象的全局有$store这个对象
<template> <div> <h1>全局仓库state对象的a值:{{$store.state.a}}</h1> </div> </template> <script> export default { created(){ console.log(this) console.log(this.$store.state.a) } } </script>
以前作的日历组件将数据放到了App.vue最大父组件上,而且还有:year、:month、:setYear、:setMonth等一系列的参数传递操做。
可是Vuex就是将数据放到了全局store中,注意:
无论项目有多大,store只有一个
只要配置正确,组件内部可使用$store便可访问store的全局数据
改变 store 中的状态(数据)的惟一途径就是经过commit()函数提交 mutation。
如下的描述来自于官方:https://vuex.vuejs.org/zh/guide/
再次强调,咱们经过提交 mutation 的方式,而非直接改变 store.state.a,是由于咱们想要更明确地追踪到状态的变化。这个简单的约定可以让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让咱们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,咱们甚至能够实现如时间穿梭般的调试体验。
因为 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅须要在计算属性中返回便可。触发变化也仅仅是在组件的 methods 中提交 mutation。
更改 Vuex 的 store 中的状态的惟一方法是提交 mutation。Vuex中的mutation很是相似于事件:每一个 mutation都有一个字符串的 事件类型(type) 和一个回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数:
你不能直接调用一个mutation handler。这个选项更像是事件注册:当触发一个type类型为JIA的 mutation时,调用此函数。要唤醒一个mutation函数,你须要以相应的type调用store.commit()方法:
main.js
import Vue from 'vue'; import Vuex from 'vuex'; //引入Vuex包 import App from './App.vue'; Vue.use(Vuex); //将vuex安装到vue中 //建立一个仓库,而且存放一些全局数据(存放四大选项) const store = new Vuex.Store({ state : { a : 100 }, mutations : { // 这里的函数只能经过commit()触发,其余操做是没法影响的 JIA(state){ state.a++ }, MINUS(state){ state.a-- } } })
App.vue
<template> <div> <h1>全局仓库state对象的a:{{$store.state.a}}</h1> <button @click="add()">+</button> <button @click="minus()">-</button> </div> </template> <script> export default { methods:{ add(){ // this.$store.state.a++ //不容许直接改全局的state数据 this.$store.commit("JIA"); }, minus(){ this.$store.commit("MINUS"); } } }; </script>
Vuex自带一个日志插件(vue-logger)用于调试:
import createLogger from 'vuex/dist/logger' const store = new Vuex.Store({ plugins: [createLogger()] })
总结:
只有mutations中能够改变state,其余任何方式都不能改state的值
组件想要改变store中的state,只能经过commit()发出一条命令。
你能够向 store.commit() 传入额外的参数,即 mutation 的 载荷(payload),在大多数状况下,载荷应该是一个对象,这样能够包含多个字段而且记录的 mutation 会更易读:
main.js
import Vue from 'vue'; import Vuex from 'vuex'; //引入Vuex包 import App from './App.vue'; import createLogger from 'vuex/dist/logger'; Vue.use(Vuex); //将vuex安装到vue中 //建立一个仓库,而且存放一些全局数据(存放四大选项) const store = new Vuex.Store({ state : { a : 100 }, mutations : { // 这里的函数只能经过commit()触发,其余操做是没法影响的 JIA(state,payload){ state.a += payload.n }, MINUS(state, payload){ state.a -= payload.n } }, plugins: [createLogger()] })
App.vue
<template> <div> <h1>全局仓库state对象的a:{{$store.state.a}}</h1> <button @click="add()">+</button> <button @click="minus()">-</button> <button @click="add(2)">+</button> <input type="text" ref="txt"> <button @click="addUser()">加用户输入的数</button> </div> </template> <script> export default { methods:{ add(n=1){ // this.$store.state.a++ //不容许直接改全局的state数据 // this.$store.commit("JIA", 8); this.$store.commit("JIA", {n}); }, minus(){ this.$store.commit("MINUS", {n : 10}); }, addUser(){ this.$store.commit("JIA", {n : Number(this.$refs.txt.value)}); } } }; </script>
记住一条重要的原则:mutations必须是同步函数
上面说过mutation 中不能写异步语句,为了处理异步操做,咱们来看一看action
action 相似于 mutation,不一样在于:
action 提交的是 mutation,而不是直接变动状态。
action 能够包含任意异步操做。
action 要经过 store.dispatch() 方法触发
注意:涉及到异步Ajax请求数据,案例必须运行在服务器端(127.0.0.1)
新建一个data文件夹,建立txt文件。使用ajax 异步读取文本文件中数据:
App.vue父组件:
<script> export default { methods:{ add(){ this.$store.dispatch("JIA"); } } } </script>
main.js
const store = new Vuex.Store({ state : { a : 100 }, mutations : { JIA(state,payload){ console.log("只有commit命令能触发我") state.a += payload.n } }, actions : { async JIA({commit}){ // console.log("只有dispatch命令能触发我,这里能够写异步语句") var data = await fetch('../data/1.txt').then(data=>data.json()) //action提交的是mutation,而不是直接更改状态, //请求成功返回的数据须要经过commit命令mutations去修改state中的数据 // context.commit("JIA", {n: data}) // this.commit("JIA", {n: data}) commit("JIA", {n:data}) } }, plugins: [createLogger()] })
actions中的函数,天生自带默认参数
一些概念:
action 函数接受一个与store实例具备相同方法和属性context对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters。当咱们在以后介绍到 Modules 时,你就知道 context 对象为何不是 store 实例自己了。
实践中,会常常用到ES2015的 参数解构 来简化代码(特别是咱们须要调用commit不少次的时候):
actions:{ async JIA({commit}){ var data = await fetch("../data/1.txt").then(data=>data.json()); commit("JIA",data) } },
action 经过 store.dispatch() 方法触发:
methods:{ add(){ this.$store.dispatch("JIA") } }
乍一眼看上去感受画蛇添足,咱们直接分发 mutation 岂不更方便?实际上并不是如此,还记得 mutation 必须同步执行这个限制么?Action 就不受约束!咱们能够在 action 内部执行异步操做:
actions支持一样的载荷方式和对象方式进行分发:
vuex单向数据流动的图示:
使用 Vuex 并不意味着你须要将全部的状态放入Vuex。虽然将全部的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。若是有些状态严格属于单个组件,最好仍是做为组件的局部状态。你应该根据你的应用开发须要进行权衡和肯定。
有时候咱们须要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
computed: { arr() { return this.$store.state.todos.filter(todo => todo.done).length } }
在Vuex中,getter相似于组件中的computed,表示state的一些计算后的值。
若是有多个组件须要用到此属性,咱们要么复制这个函数,或者抽取到一个共享函数而后在多处导入它——不管哪一种方式都不是很理想。
Vuex 容许咱们在 store 中定义“getter”(能够认为是 store 的计算属性)。就像computed计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。
Getter 接受 state 做为其第一个参数:
main.js
import Vue from 'vue'; import Vuex from 'vuex'; //引入Vuex包 import App from './App.vue'; import createLogger from 'vuex/dist/logger'; //调试工具 Vue.use(Vuex); //将Vuex安装到全局 //建立一个仓库,而且存放以一些全局数据(存放四大选项) const store = new Vuex.Store({ state:{ a:100, students:[ {name:"小明",sex:"男"}, {name:"小红",sex:"女"}, {name:"小刚",sex:"男"}, {name:"小花",sex:"女"}, {name:"小黑",sex:"男"} ] }, getters:{ //获得全部男生 nan(state){ return state.students.filter((item)=>{ return item.sex == '男'; }) }, //获得全部女生 nv(state){ return state.students.filter((item)=>{ return item.sex == '女'; }) }, //获得男生和女生的个数,getter也能够接受getter做为第二个参数 nanCount(state,getters){ return getters.nan.length; }, nvCount(state,getters){ return getters.nv.length; } }, plugins: [createLogger()] }) new Vue({ el:"#app", store, //将store注入到全局 render:(h)=> h(App) })
App.vue父组件:
<template> <div> <h1>{{students}}</h1> <h2>男生:{{$store.getters.nanCount}}个</h2> <h2>女生:{{$store.getters.nvCount}}个</h2> <button @click="nan">查看男生</button> <button @click="nv">查看女生</button> <button @click="all">查看所有</button> </div> </template> <script> export default { data(){ return { isState:'all' } }, computed:{ students(){ if(this.isState == 'all'){ return this.$store.state.students; }else if(this.isState == 'nan'){ return this.$store.getters.nan; }else if(this.isState == 'nv'){ return this.$store.getters.nv } } }, methods:{ nan(){ this.isState = 'nan' }, nv(){ this.isState = 'nv' }, all(){ this.isState = 'all' } } } </script>
在介绍state中咱们了解到,在Store仓库里,state就是用来存放数据,如果对数据进行处理输出,好比数据要过滤,通常咱们能够写到computed中。可是若是不少组件都使用这个过滤后的数据,好比饼状图组件和曲线图组件,咱们是否能够把这个数据抽提出来共享?这就是getters存在的意义。官网说的很清楚,getters是store的计算属性。
getters上简单来讲就是存放一些公共函数供组件调用。getters 会暴露为 $store.getters 对象,也就是说能够经过 $store.getters[属性]来进行相应的调用。
4.6vuex的命名空间
目录结构:
│ package.json
│ webpack.config.js
│
└─www
│ index.html
│
└─app
│ App.vue
│ main.js
│
├─components
└─store
│ index.js
│
├─counter
│ store.js
│
└─taobao
store.js
{ "name": "vue_study", "version": "1.0.0", "description": "", "main": "webpack.config.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --content-base ./www --port 8080" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "vue": "^2.5.17", "vuex": "^3.0.1" }, "devDependencies": { "css-loader": "^1.0.1", "style-loader": "^0.23.1", "vue-loader": "^15.4.2", "vue-style-loader": "^4.1.2", "vue-template-compiler": "^2.5.17", "webpack": "^4.9.1", "webpack-cli": "^3.1.2" } }
const path = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { //程序的入口文件 entry: "./www/app/main.js", //程序的出口(打包的文件) output: { //打包文件输出的路径 path: path.resolve(__dirname, "./www/dist"), //打包文件的名称 filename: 'all.js', publicPath: "/public" //这是对webpack-dev-server的配置,配置虚拟路径 }, //监听文件的变化(自动打包) watch: true, mode: "development", //配置webpack模块插件 module: { //关于模块的配置规则 rules: [{ // 模块规则(配置 loader、解析器等选项) test: /\.js?$/, //解析的时候匹配js文件 //翻译什么文件夹中的文件 include: [path.resolve(__dirname, "www/app")], //不翻译什么文件夹中的文件 exclude: [path.resolve(__dirname, "node_modules")], // loader:"babel-loader", //配置翻译语法 // options:{ // presets:["es2015","es2016"] // } }, { test: /\.vue$/, loader: 'vue-loader', include: [path.resolve(__dirname, "www/app")], exclude: [path.resolve(__dirname, "node_modules")], options: { loaders: { js: 'babel-loader!eslint-loader' } } }, { test: /\.css$/, include: [path.resolve(__dirname, "www/app")], exclude: [path.resolve(__dirname, "node_modules")], use: ['vue-style-loader', 'css-loader'], }, { test: /\.styl(us)?$/, use: [ 'vue-style-loader', 'css-loader', 'stylus-loader' ] } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js' } }, //最新版webpack须要引入此插件 plugins: [ new VueLoaderPlugin() ], //webpack设置代理跨越 devServer: { proxy: { '/api': { target: 'http://127.0.0.1:3000', //设置你调用的接口域名和端口 //这里理解成/api代理target中的地址,后面组件中调用接口要使用/api代替 pathRewrite: { '^/api': '' } } } } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <div id="app"></div> </body> <script type="text/javascript" src="public/all.js"></script> </html>
<template> <div> <h1>counter的{{$store.state.counterStore.a}}</h1> <h1>taobao的{{$store.state.taobaoStore.a}}</h1> <button @click="add">触发counter的ADD</button> </div> </template> <script> export default { methods:{ add(){ //根据命名空间发出异步 this.$store.dispatch("counterStore/ADD") } } } </script>
import Vue from "vue"; import App from "./App.vue"; import store from "./store"; new Vue({ el: "#app", store,//引入store文件夹中的index.js render: (h) => h(App) })
import Vue from "vue"; import Vuex from "vuex"; import counterStore from "./counter/store.js";//引入counter的store import taobaoStore from "./taobao/store.js";//引入taobao的store import createLogger from 'vuex/dist/logger'; Vue.use(Vuex); export default new Vuex.Store({ modules: {//放入modules counterStore, taobaoStore }, plugins : [createLogger()] })
export default { namespaced: true, //命名空间 state : { a:100 }, mutations : { ADD(state,payload){ state.a++//上面的state } }, actions : { ADD({commit}){ commit("ADD")//调用上面mutations的ADD } } }
export default { namespaced: true,//开启命名空间跟上面同样的用法 state : { a:200 }, mutations : {}, actions : {} }
通常状况下,一个应用的数据都须要等待后端接口人员开发完对应的接口才能够获取到,这样子的效率有点低。最好是咱们能够本身模拟接口数据,进行页面的数据填充,打通全部关节,以后等接口开发好了,改下接口地址就行了。
因此,做为前端和客户端开发人员,在后端尚未给出对应的api接口时,咱们没法作测试。
这时,咱们可使用json-server快速搭建一个测试的api接口,能在几十秒以内搭建好。
json-server 它能模拟“数据库”,提供了一套简单的API(RESTFUL)接口。
在开发过程当中,先后端不管是否分离,接口多半是滞后于页面开发的。因此创建一个RESTFUL风格的API接口,给前端页面提供虚拟的数据,是很是有必要的。
由于它足够简单,写少许数据,便可使用。
也由于它足够强大,支持CORS和JSONP跨域请求,支持GET, POST, PUT, PATCH 和 DELETE 方法,更提供了一系列的查询方法,如limit,order等。下面将详细介绍 json-server 的使用。