├── vue10
└── demo
│ ├── src
│ ├── style.css
│ ├── images
│ │ └── image.png
│ ├── title.vue
│ ├── button.vue
│ ├── app.vue
│ └── index.js
│ ├── .babelrc
│ ├── index.html
│ ├── index.ejs
│ ├── package.json
│ ├── webpack.prod.config.js
│ └── webpack.config.js
├── vue11
├── router
│ ├── src
│ │ ├── style.css
│ │ ├── images
│ │ │ └── image.png
│ │ ├── views
│ │ │ ├── index.vue
│ │ │ ├── user.vue
│ │ │ └── about.vue
│ │ ├── app.vue
│ │ └── index.js
│ ├── .babelrc
│ ├── index.html
│ ├── index.ejs
│ ├── webpack.prod.config.js
│ ├── package.json
│ └── webpack.config.js
├── vue-bus
│ ├── src
│ │ ├── style.css
│ │ ├── images
│ │ │ └── image.png
│ │ ├── app.vue
│ │ ├── views
│ │ │ ├── user.vue
│ │ │ ├── about.vue
│ │ │ ├── Counter.vue
│ │ │ └── index.vue
│ │ ├── moduleA.js
│ │ ├── vue-bus.js
│ │ └── index.js
│ ├── .babelrc
│ ├── index.html
│ ├── index.ejs
│ ├── webpack.prod.config.js
│ ├── package.json
│ └── webpack.config.js
└── vuex
│ ├── src
│ ├── style.css
│ ├── images
│ │ └── image.png
│ ├── app.vue
│ ├── views
│ │ ├── user.vue
│ │ ├── about.vue
│ │ └── index.vue
│ ├── moduleA.js
│ └── index.js
│ ├── .babelrc
│ ├── index.html
│ ├── index.ejs
│ ├── webpack.prod.config.js
│ ├── package.json
│ └── webpack.config.js
├── vue07
├── input_box
│ ├── index.js
│ ├── input-number.html
│ └── input-number.js
├── vue7-02.html
├── vue7-26.html
├── vue7-07.html
├── vue7-04.html
├── label_page
│ ├── pane.js
│ ├── style.css
│ ├── tabs.html
│ └── tabs.js
├── vue7-01.html
├── vue7-09.html
├── vue7-11.html
├── vue7-03.html
├── vue7-05.html
├── vue7-06.html
├── vue7-18.html
├── vue7-10.html
├── vue7-23.html
├── vue7-29.html
├── vue7-27.html
├── vue7-20.html
├── vue7-08.html
├── vue7-24.html
├── vue7-30.html
├── vue7-16.html
├── vue7-17.html
├── vue7-25.html
├── vue7-19.html
├── vue7-14.html
├── vue7-21.html
├── vue7-15.html
├── vue7-28.html
├── vue7-22.html
├── vue7-13.html
└── vue7-12.html
├── vue13
├── daily
│ ├── .babelrc
│ ├── src
│ │ ├── images
│ │ │ └── image.png
│ │ ├── index.js
│ │ ├── title.vue
│ │ ├── components
│ │ │ ├── item.vue
│ │ │ └── daily-article.vue
│ │ ├── button.vue
│ │ ├── libs
│ │ │ └── util.js
│ │ ├── directives
│ │ │ └── time.js
│ │ ├── style.css
│ │ └── app.vue
│ ├── index.html
│ ├── index.ejs
│ ├── webpack.prod.config.js
│ ├── package.json
│ ├── proxy.js
│ └── webpack.config.js
└── README13.md
├── vue14
└── shopping
│ ├── .babelrc
│ ├── src
│ ├── images
│ │ └── image.png
│ ├── views
│ │ ├── user.vue
│ │ ├── about.vue
│ │ ├── index.vue
│ │ └── product.vue
│ ├── router.js
│ ├── app.vue
│ ├── style.css
│ ├── components
│ │ └── product.vue
│ ├── product.js
│ └── index.js
│ ├── index.html
│ ├── index.ejs
│ ├── webpack.prod.config.js
│ ├── package.json
│ └── webpack.config.js
├── vue08
├── v-time
│ ├── index.js
│ ├── index.html
│ └── time.js
├── menu
│ ├── index.js
│ ├── index.html
│ ├── style.css
│ └── clickoutside.js
└── vue8-01.html
├── vue05
├── shopping_trolley
│ ├── shopping.css
│ ├── shopping.js
│ └── shopping.html
├── vue5-01.html
├── vue5-02.html
├── vue5-05.html
├── vue5-08.html
├── vue5-07.html
├── vue5-03.html
├── vue5-06.html
├── vue5-09.html
├── vue5-12.html
├── vue5-04.html
├── vue5-10.html
└── vue5-11.html
├── vue02
├── vue2-07.html
├── vue2-10.html
├── vue2-01.html
├── vue2-04.html
├── vue2-08.html
├── vue2-05.html
├── vue2-02.html
├── vue2-03.html
├── vue2-09.html
└── vue2-06.html
├── vue04
├── vue4-01.html
├── vue4-04.html
├── vue4-06.html
├── vue4-09.html
├── vue4-08.html
├── vue4-02.html
├── vue4-10.html
├── vue4-05.html
├── vue4-07.html
└── vue4-03.html
├── vue01
├── vue1-01.html
└── vue1-02.html
├── vue09
├── sort_form
│ ├── index.html
│ ├── style.css
│ ├── index.js
│ └── table.js
├── vue9-03.html
├── vue9-12.html
├── message_list
│ ├── index.js
│ ├── index.html
│ ├── list.js
│ ├── input.js
│ └── style.css
├── vue9-08.html
├── vue9-07.html
├── vue9-02.html
├── vue9-04.html
├── vue9-09.html
├── vue9-10.html
├── vue9-05.html
├── vue9-11.html
├── vue9-01.html
├── vue9-06.html
└── vue9-13.html
├── vue03
├── vue3-01.html
├── vue3-04.html
├── vue3-03.html
└── vue3-02.html
├── vue15
└── README15.md
├── vue06
├── vue6-03.html
├── vue6-01.html
├── vue6-06.html
├── vue6-08.html
├── vue6-05.html
├── vue6-02.html
├── vue6-07.html
└── vue6-04.html
├── vue12
└── README12.md
└── README.md
/vue10/demo/src/style.css:
--------------------------------------------------------------------------------
1 | #app{
2 | font-size: 24px;
3 | color:#f50;
4 | }
5 |
--------------------------------------------------------------------------------
/vue11/router/src/style.css:
--------------------------------------------------------------------------------
1 | #app{
2 | font-size: 24px;
3 | color:#f50;
4 | }
5 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/style.css:
--------------------------------------------------------------------------------
1 | #app{
2 | font-size: 24px;
3 | color:#f50;
4 | }
5 |
--------------------------------------------------------------------------------
/vue11/vuex/src/style.css:
--------------------------------------------------------------------------------
1 | #app{
2 | font-size: 24px;
3 | color:#f50;
4 | }
5 |
--------------------------------------------------------------------------------
/vue07/input_box/index.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{
4 | value:5
5 | }
6 | })
--------------------------------------------------------------------------------
/vue10/demo/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue11/router/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue11/vuex/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue13/daily/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue11/vue-bus/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue14/shopping/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets":["env"],
3 | "plugins":["transform-runtime"],
4 | "comments":false
5 | }
--------------------------------------------------------------------------------
/vue10/demo/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue10/demo/src/images/image.png
--------------------------------------------------------------------------------
/vue11/vuex/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue11/vuex/src/images/image.png
--------------------------------------------------------------------------------
/vue13/daily/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue13/daily/src/images/image.png
--------------------------------------------------------------------------------
/vue11/router/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue11/router/src/images/image.png
--------------------------------------------------------------------------------
/vue11/router/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 首页
3 |
4 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue11/vue-bus/src/images/image.png
--------------------------------------------------------------------------------
/vue14/shopping/src/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyf711/vue-combat-book/HEAD/vue14/shopping/src/images/image.png
--------------------------------------------------------------------------------
/vue08/v-time/index.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{
4 | timeNow : (new Date()).getTime(),
5 | timeBefore : 1488930695721
6 | }
7 | })
--------------------------------------------------------------------------------
/vue08/menu/index.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{
4 | show:false
5 | },
6 | methods:{
7 | handleClose:function(){
8 | this.show = false
9 | }
10 | }
11 | })
--------------------------------------------------------------------------------
/vue13/daily/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './app.vue';
3 | import './style.css';
4 |
5 | new Vue({
6 | el: '#app',
7 | render: h => {
8 | return h(App);
9 | }
10 | });
11 |
--------------------------------------------------------------------------------
/vue14/shopping/src/views/user.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ $route.params.id }}
3 |
4 |
5 |
--------------------------------------------------------------------------------
/vue11/vuex/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/vue11/router/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/vue11/router/src/views/user.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ $route.params.id }}
3 |
4 |
11 |
--------------------------------------------------------------------------------
/vue11/vuex/src/views/user.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ $route.params.id }}
3 |
4 |
11 |
--------------------------------------------------------------------------------
/vue14/shopping/src/views/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/vue10/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/views/user.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ $route.params.id }}
3 |
4 |
11 |
--------------------------------------------------------------------------------
/vue11/vuex/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue10/demo/src/title.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
--------------------------------------------------------------------------------
/vue11/router/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue11/vue-bus/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue13/daily/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue13/daily/src/title.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
--------------------------------------------------------------------------------
/vue14/shopping/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | webpack app
6 |
7 |
8 |
9 |
10 | Hello world
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/moduleA.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | useName: "sam", // 模块内部的state是局部的,所以任何组件通过this.$store.state.moduleA.useName读取
3 | count:10
4 | };
5 | const getters ={ //模块内部getter、mutation和action,仍然注册在全局命名空间内
6 | sumCount(state,getters,rootState){
7 | return state.count + rootState.count
8 | }
9 | }
10 | export default {
11 | state,
12 | getters
13 | }
--------------------------------------------------------------------------------
/vue11/vuex/src/moduleA.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | useName: "sam", // 模块内部的state是局部的,所以任何组件通过this.$store.state.moduleA.useName读取
3 | count:10
4 | };
5 | const getters ={ //模块内部getter、mutation和action,仍然注册在全局命名空间内
6 | sumCount(state,getters,rootState){
7 | return state.count + rootState.count
8 | }
9 | }
10 | export default {
11 | state,
12 | getters
13 | }
--------------------------------------------------------------------------------
/vue05/shopping_trolley/shopping.css:
--------------------------------------------------------------------------------
1 | [v-cloak]{display: none;}
2 | table{
3 | border: 1px solid #e9e9e9;
4 | border-spacing: 0;
5 | empty-cells: show;
6 | }
7 | th,td{
8 | padding: 8px 16px;
9 | text-align: left;
10 | border: 1px solid #e9e9e9;
11 | }
12 | th{
13 | background: #f7f7f7;
14 | color:#5c6b77;
15 | font-weight: 600;
16 | white-space: nowrap;
17 | }
--------------------------------------------------------------------------------
/vue10/demo/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue11/router/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue11/vuex/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue13/daily/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue11/vue-bus/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue14/shopping/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webpack App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/vue-bus.js:
--------------------------------------------------------------------------------
1 | const install = function(Vue){
2 | const Bus = new Vue({
3 | methods:{
4 | emit(event, ...args){
5 | this.$emit(event, ...args);
6 | },
7 | on(event,callback){
8 | this.$on(event,callback);
9 | },
10 | off(event,callback){
11 | this.$off(event,callback);
12 | }
13 | }
14 | });
15 | Vue.prototype.$bus = Bus;
16 | };
17 |
18 | export default install;
--------------------------------------------------------------------------------
/vue11/router/src/views/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
介绍页
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/views/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
介绍页
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/vue11/vuex/src/views/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
介绍页
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/views/Counter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ numbe }}
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/vue02/vue2-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-07
6 |
7 |
8 |
11 |
12 |
13 |
21 |
22 |
--------------------------------------------------------------------------------
/vue08/v-time/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 开发实时时间转换v-time
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/vue07/input_box/input-number.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 数字输入框组件
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/vue04/vue4-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-01
6 |
7 |
8 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/vue04/vue4-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-04
6 |
7 |
8 |
12 |
13 |
22 |
23 |
--------------------------------------------------------------------------------
/vue04/vue4-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-06
6 |
7 |
8 |
12 |
13 |
22 |
23 |
--------------------------------------------------------------------------------
/vue13/daily/src/components/item.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 | {{ data.title }}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/vue04/vue4-09.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-09
6 |
7 |
8 |
11 |
12 |
24 |
25 |
--------------------------------------------------------------------------------
/vue04/vue4-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-08
6 |
7 |
8 |
12 |
13 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/vue05/vue5-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-01
6 |
9 |
10 |
11 |
12 |
13 | {{message}}
14 |
15 |
16 |
24 |
25 |
--------------------------------------------------------------------------------
/vue02/vue2-10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-10
6 |
7 |
8 |
9 |
10 |
11 |
25 |
26 |
--------------------------------------------------------------------------------
/vue02/vue2-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-01
6 |
7 |
8 |
9 |
10 |
你好, {{ name }}
11 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/vue04/vue4-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-02
6 |
7 |
8 |
12 |
13 |
22 |
23 |
--------------------------------------------------------------------------------
/vue05/vue5-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-02
6 |
7 |
8 |
9 |
10 |
{{message}}
11 |
12 | {{message}}
13 |
14 |
15 |
16 |
24 |
25 |
--------------------------------------------------------------------------------
/vue02/vue2-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-04
6 |
7 |
8 |
9 |
10 | {{这里的内容不会被编辑}}
11 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/vue04/vue4-10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-10
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 |
25 |
--------------------------------------------------------------------------------
/vue07/vue7-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-02
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
--------------------------------------------------------------------------------
/vue01/vue1-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue1-01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
25 |
26 |
--------------------------------------------------------------------------------
/vue01/vue1-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue1-02
6 |
7 |
8 |
13 |
14 |
26 |
27 |
--------------------------------------------------------------------------------
/vue04/vue4-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-05
6 |
7 |
8 |
12 |
13 |
23 |
24 |
--------------------------------------------------------------------------------
/vue07/vue7-26.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-26
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
25 |
--------------------------------------------------------------------------------
/vue09/sort_form/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 可排序的表格组件
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/vue05/vue5-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-05
6 |
7 |
8 |
9 |
当status为1时显示该行
10 |
11 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/vue03/vue3-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue3-01
6 |
7 |
8 |
9 | {{ reversedText }}
10 |
11 |
12 |
13 |
26 |
27 |
--------------------------------------------------------------------------------
/vue07/vue7-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-07
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
23 |
24 |
--------------------------------------------------------------------------------
/vue08/vue8-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue8-01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
--------------------------------------------------------------------------------
/vue07/vue7-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-04
6 |
7 |
8 |
9 |
10 |
11 |
12 |
26 |
27 |
--------------------------------------------------------------------------------
/vue07/label_page/pane.js:
--------------------------------------------------------------------------------
1 | Vue.component('pane',{
2 | name:'pane', //为getTabs()遍历所有name为pane的子组件做准备,所以这里起个name
3 | template:'\
4 | \
5 |
',//上边的slot是为了能显示标签里边的内容。
6 | data:function(){
7 | return { sw:true }
8 | },
9 | props:{
10 | name:{ //pane的标识
11 | type:String
12 | },
13 | label:{ //标签页标题
14 | type:String,
15 | default:'as'
16 | }
17 | },
18 | methods:{
19 | updateNav(){
20 | this.$parent.updateNav();
21 | }
22 | },
23 | watch:{
24 | label(){
25 | this.updateNav();
26 | }
27 | },
28 | mounted(){
29 | this.updateNav();
30 | }
31 | })
--------------------------------------------------------------------------------
/vue08/menu/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 从外部关闭的下拉菜单
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
下拉菜单内容,点击外面区域可以关闭
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/vue07/vue7-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 |
25 |
--------------------------------------------------------------------------------
/vue09/sort_form/style.css:
--------------------------------------------------------------------------------
1 | [v-cloak]{
2 | display: none;
3 | }
4 | table{
5 | width: 100%;
6 | margin-bottom: 24px;
7 | border-collapse: collapse;
8 | border-spacing: 0;
9 | empty-cells: show;
10 | border:1px solid #e9e9e9;
11 | }
12 | table th{
13 | background: #f7f7f7;
14 | color: #5c6b77;
15 | font-weight: 600;
16 | white-space: nowrap;
17 | }
18 | table td,table th{
19 | padding:8px 16px;
20 | border: 1px solid #e9e9e9;
21 | text-align:left;
22 | }
23 | table th a{
24 | display: inline-block;
25 | margin: 0 4px;
26 | cursor: pointer;
27 | }
28 | table th a.on{
29 | color: #3399ff;
30 | }
31 | table th a:hover{
32 | color: #3399ff;
33 | }
--------------------------------------------------------------------------------
/vue07/vue7-09.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-09
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
25 |
--------------------------------------------------------------------------------
/vue03/vue3-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue3-04
6 |
7 |
8 |
9 | {{ reversedText }}
10 |
11 |
28 |
29 |
--------------------------------------------------------------------------------
/vue09/vue9-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-03
6 |
7 |
8 |
9 |
10 |
11 |
12 |
29 |
30 |
--------------------------------------------------------------------------------
/vue09/vue9-12.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-12
6 |
7 |
8 |
12 |
13 |
27 |
28 |
--------------------------------------------------------------------------------
/vue02/vue2-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-08
6 |
7 |
8 |
9 |
百度一下
10 |
![]()
11 |
12 |
13 |
14 |
15 |
24 |
25 |
--------------------------------------------------------------------------------
/vue07/vue7-11.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-11
6 |
7 |
8 |
9 |
10 |
11 |
12 |
29 |
30 |
--------------------------------------------------------------------------------
/vue02/vue2-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-05
6 |
7 |
8 |
9 | {{ number / 10 }}
10 | {{ isOK ? '确定' : '取消' }}
11 | {{ text.split(',').reverse().join(',') }}
12 |
19 |
20 |
21 |
31 |
32 |
--------------------------------------------------------------------------------
/vue07/vue7-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-03
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/vue10/demo/src/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
28 |
--------------------------------------------------------------------------------
/vue13/daily/src/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
28 |
--------------------------------------------------------------------------------
/vue02/vue2-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-02
6 |
7 |
8 |
9 |
10 |
24 |
25 |
--------------------------------------------------------------------------------
/vue02/vue2-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-03
6 |
7 |
8 | {{date}}
9 |
10 |
11 |
29 |
30 |
--------------------------------------------------------------------------------
/vue08/menu/style.css:
--------------------------------------------------------------------------------
1 | [v-cloak]{
2 | display: none;
3 | }
4 | .main{
5 | width: 125px;
6 | }
7 | button{
8 | display: block;
9 | width: 100%;
10 | color:#fff;
11 | background-color: #39f;
12 | border: 0;
13 | padding: 6px;
14 | text-align:center;
15 | font-size: 12px;
16 | border-radius: 4px;
17 | cursor: pointer;
18 | outline:none;
19 | position:relative;
20 | }
21 | button:active{
22 | top: 1px;
23 | left:1px;
24 | }
25 | .dropdown{
26 | width:100%;
27 | height: 150px;
28 | margin: 5px 0;
29 | font-size: 12px;
30 | background-color: #fff;
31 | border-radius: 4px;
32 | box-shadow: 0 1px 6px rgba(0,0,0,.2);
33 | /*display: none;*/
34 | }
35 | .dropdown p{
36 | display: inline-block;
37 | padding: 6px;
38 | }
--------------------------------------------------------------------------------
/vue07/vue7-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-05
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
28 |
29 |
--------------------------------------------------------------------------------
/vue14/shopping/src/router.js:
--------------------------------------------------------------------------------
1 | const routers = [
2 | {
3 | path: '/list',
4 | meta: {
5 | title: '商品列表'
6 | },
7 | component: (resolve) => require(['./views/list.vue'], resolve)
8 | },
9 | {
10 | path: '/product/:id',
11 | meta: {
12 | title: '商品详情'
13 | },
14 | component: (resolve) => require(['./views/product.vue'], resolve)
15 | },
16 | {
17 | path: '/cart',
18 | meta: {
19 | title: '购物车'
20 | },
21 | component: (resolve) => require(['./views/cart.vue'], resolve)
22 | },
23 | {
24 | path: '*',
25 | redirect: '/list'
26 | }
27 | ];
28 | export default routers;
--------------------------------------------------------------------------------
/vue15/README15.md:
--------------------------------------------------------------------------------
1 | # 相关开源项目介绍
2 |
3 | ### 服务端渲染与Nuxt.js
4 | Vue.js2支持服务端渲染。
5 | 服务端渲染(SSR):指的是渲染内容。打开页面,查看源代码。文字都在源代码里面,就是SSR。或chrome的network面板查看有没有相关异步请求来调取内容来判断。
6 |
7 | 很多网站之所以用SSR,主要目的是做SEO。另一个目的是客户端的网络可能不稳定,通过SSR减少请求量和客户端渲染。可以相对快速看到内容。
8 |
9 | Nuxt.js:基于Vue.js的通用应用框架。为Node.js做Vue的服务端渲染提供了各种配置。快速搭建一套SSR框架。
10 | Nuxt.js构建的代码,UI在服务端渲染。查看代码所有模板内容直接渲染在其中。
11 | [Vue.js服务端渲染](https://ssr.vuejs.org/)
12 | [Nuxt.js文档](https://nuxtjs.org/)
13 |
14 | ### HTTP库axios
15 | [项目地址](https://github.com/mzabriskie/axios)
16 | axios是一个基于Promise,同时支持浏览器端和Node.js的HTTP库。常用语Ajax请求。
17 |
18 | ### 多语言插件 vue-i18n
19 | [项目地址](https://gitbub.com/kazupon/vue-i18n)
20 | vue-i18n是一个vue.js插件。提供了都语言解决方案。如果你的项目有多国语言的需求,可以使用它很快地实现。
21 |
--------------------------------------------------------------------------------
/vue04/vue4-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-07
6 |
7 |
8 |
9 |
10 |
11 |
12 |
32 |
33 |
--------------------------------------------------------------------------------
/vue06/vue6-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-03
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/vue14/shopping/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/vue05/vue5-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-08
6 |
7 |
8 |
9 |
{{value}}
10 |
11 | - {{ index }} - {{ key }} : {{ value }}
12 |
13 |
14 |
{{n}}
15 |
16 |
17 |
18 |
30 |
31 |
--------------------------------------------------------------------------------
/vue09/message_list/index.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{
4 | username:'',
5 | message:'',
6 | list:[]
7 | },
8 | methods:{
9 | // 给list添加一条留言数据
10 | handleSend:function(){
11 | if( this.username === '' ){ window.alert('请输入昵称'); return }
12 | if( this.message === '' ){ window.alert('请输入留言内容'); return }
13 | this.list.push({
14 | name:this.username,
15 | message:this.message
16 | });
17 | this.message = '';
18 | },
19 | handleReply:function(index){
20 | var name = this.list[index].name;
21 | this.message = '@回复' + name + ':';
22 | // $refs不是响应式的,不应该用它绑定数据。只是方便取和操作DOM
23 | // $refs讲解 https://www.cnblogs.com/xumqfaith/p/7743387.html
24 | this.$refs.message.focus();
25 | }
26 | }
27 | })
--------------------------------------------------------------------------------
/vue02/vue2-09.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-09
6 |
7 |
8 |
9 |
这是一段文本
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
30 |
31 |
--------------------------------------------------------------------------------
/vue04/vue4-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue4-03
6 |
7 |
8 |
12 |
13 |
31 |
32 |
--------------------------------------------------------------------------------
/vue07/vue7-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-06
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
28 |
29 |
--------------------------------------------------------------------------------
/vue07/vue7-18.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-18
6 |
7 |
8 |
9 |
10 |
11 |
12 | 分发的内容
13 | 更多分发的内容
14 |
15 |
16 |
17 |
27 |
28 |
--------------------------------------------------------------------------------
/vue05/vue5-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-07
6 |
7 |
8 |
9 |
10 |
11 | - 书名:{{ book.name }}
12 | - 作者:{{ book.author }}
13 |
14 |
15 |
16 |
17 |
36 |
37 |
--------------------------------------------------------------------------------
/vue07/vue7-10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-10
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
--------------------------------------------------------------------------------
/vue07/vue7-23.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-23
6 |
7 |
8 |
9 |
10 |
11 |
12 |
30 |
31 |
--------------------------------------------------------------------------------
/vue14/shopping/src/style.css:
--------------------------------------------------------------------------------
1 | *{
2 | margin: 0;
3 | padding: 0;
4 | }
5 | a{
6 | text-decoration: none;
7 | }
8 | body{
9 | background: #f8f8f9;
10 | }
11 | .header{
12 | height: 48px;
13 | line-height: 48px;
14 | background: rgba(0,0,0,.8);
15 | color: #fff;
16 | }
17 | .header-title{
18 | padding: 0 32px;
19 | float: left;
20 | color: #fff;
21 | }
22 | .header-menu{
23 | float: right;
24 | margin-right: 32px;
25 | }
26 | .header-menu-cart{
27 | color: #fff;
28 | }
29 | .header-menu-cart span{
30 | display: inline-block;
31 | width: 16px;
32 | height: 16px;
33 | line-height: 16px;
34 | text-align: center;
35 | border-radius: 50%;
36 | background: #ff5500;
37 | color: #fff;
38 | font-size: 12px;
39 | }
--------------------------------------------------------------------------------
/vue05/vue5-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-03
6 |
7 |
8 |
9 |
10 |
当status全等于1显示该行
11 |
当status全等于2显示该行
12 |
否则显示该行
13 |
14 |
15 |
16 | 这是一段文本
17 | 这是一段文本
18 | 这是一段文本
19 |
20 |
21 |
22 |
31 |
32 |
--------------------------------------------------------------------------------
/vue09/message_list/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 留言列表
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/vue12/README12.md:
--------------------------------------------------------------------------------
1 | # iView经典组件剖析
2 |
3 | + iView:是一套基于Vue2的开源UI组件库。主要服务于PC界面的中后台产品。
4 | + 官网:https://www.iviewui.com/
5 | + github:https://github.com/iview/iview
6 |
7 | 独立组件与业务组件最大的不同是,业务组件往往针对数据的获取、整理、可视化,逻辑清 晰简单,可以使用vuex:而独立组件的复杂度更多集中在细节、交互、性能优化、 API 设计上, 对原生 JavaScript 有一定考验。在使用过程中,可能会有新功能的不断添加,也会发现隐藏的 bug, 所以独立组件一开始逻辑和代码量并不复杂,多次选代后会越来越冗长,当然功能也更丰富,使用更稳定。万事开头难,组件 API 的设计和可扩展性决定了组件迭代的复杂性。一开始不可能考虑到所有的细节,但是整体架构要清晰可扩展,否则很有可能重构。
8 |
9 | https://github.com/iview/iview/blob/2.0/src/components里有他的组件源码
10 |
11 | 组件间通信可以通过$emit bus vuex来实现。但iView作为独立组件无法使用bus vuex,为了实现跨组件通讯,模拟了vue1的dispatch和broadcast
12 |
13 | 级联选择组件Cascader就是用了几个组件在一起实现:
14 | cascader.vue
15 | casitem.vue
16 | caspanel.vue
17 |
18 | iView内置工具函数,比如:findComponentUpward findComponentDownward findComponentsDownward
--------------------------------------------------------------------------------
/vue07/vue7-29.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-29
6 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
31 |
32 |
--------------------------------------------------------------------------------
/vue06/vue6-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
输入的内容是: {{ message }}
13 |
14 |
15 |
输入的内容是:{{ text }}
16 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/vue07/vue7-27.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-27
6 |
7 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
--------------------------------------------------------------------------------
/vue07/vue7-20.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-20
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 | 来自父组件的内容
16 | {{ props.msg }}
17 |
18 |
19 |
20 |
21 |
30 |
31 |
--------------------------------------------------------------------------------
/vue07/vue7-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-7-08
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
29 |
30 |
--------------------------------------------------------------------------------
/vue07/vue7-24.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-24
6 |
7 |
8 |
9 |
10 |
11 |
12 |
在父组件中定义子组件的模板
13 |
{{ message }}
14 |
{{ msg }}
15 |
16 |
17 |
18 |
19 |
34 |
35 |
--------------------------------------------------------------------------------
/vue07/label_page/style.css:
--------------------------------------------------------------------------------
1 | [v-cloak]:{
2 | display: none;
3 | }
4 | .tabs{
5 | font-size: 14px;
6 | color: #657180;
7 | }
8 | /*.tabs-bar:after{
9 | content: '';
10 | display: block;;
11 | width:100%;
12 | height: 1px;
13 | background: #d7dde4;
14 | margin-top: -1px;
15 | }*/
16 | .-tabs-tab{
17 | display: inline-block;;
18 | padding: 4px 16px;
19 | margin-right: 6px;
20 | background: #fff;
21 | border: 1px solid #d7dde4;
22 | cursor: pointer;
23 | position: relative;
24 | }
25 | .tabs-tab-active{
26 | color: #3399ff;
27 | border-top: 1px solid #3399ff;
28 | border-bottom: 1px solid #fff;
29 | }
30 | /*.tabs-tab-active:before{
31 | content: '';
32 | display: block;;
33 | height: 1px;
34 | background: #3399ff;
35 | position: absolute;
36 | top: 0;
37 | left: 0;
38 | right: 0;
39 | }*/
40 | .tabs-content{
41 | padding: 8px 0;
42 | }
--------------------------------------------------------------------------------
/vue10/demo/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
点击按钮
6 |
7 |
8 |
9 |
10 |
11 |
12 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/vue06/vue6-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-06
6 |
7 |
8 |
9 |
10 |
13 |
选择的是:{{ selected }}
14 |
15 |
16 |
17 |
37 |
38 |
--------------------------------------------------------------------------------
/vue07/vue7-30.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-30
6 |
7 |
8 |
9 |
10 |
11 |
31 |
32 |
--------------------------------------------------------------------------------
/vue09/vue9-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-08
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
39 |
40 |
--------------------------------------------------------------------------------
/vue08/menu/clickoutside.js:
--------------------------------------------------------------------------------
1 | Vue.directive('clickoutside',{
2 | //bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作
3 | bind:function( el,binding,vnode ){
4 | function documentHandler(e){
5 | // 判断点击的区域是否在指令所载元素内部,是就跳出。el是指令所绑定的元素
6 | if( el.contains(e.target) ){ //contains方法用来判断A是否包含B,包含返回true
7 | return false;
8 | }
9 | if( binding.expression ){ //判断当前指令v-clickoutside有没有写表达式
10 | binding.value(e); //执行当前上下文methods中指定的函数handleClose
11 | }
12 | }
13 | //__vueClickOutside__ 是自己随便起的,el.__vueClickOutside__ 引用了documentHandler,这样就可以再后边移除监听事件
14 | el.__vueClickOutside__ = documentHandler;
15 | document.addEventListener('click',documentHandler);
16 | },
17 | unbind:function( el,binding ){
18 | document.removeEventListener('click',el.__vueClickOutside__)
19 | // 移除document的click事件监听。
20 | delete el.__vueClickOutside__;
21 | }
22 |
23 | })
--------------------------------------------------------------------------------
/vue06/vue6-08.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-08
6 |
7 |
8 |
9 |
10 |
11 |
{{ message1 }}
12 |
13 |
14 |
15 |
{{ typeof message2 }}
16 |
17 |
18 |
19 |
{{ message3 }}
20 |
21 |
22 |
32 |
33 |
--------------------------------------------------------------------------------
/vue07/vue7-16.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-16
6 |
7 |
8 |
9 |
10 |
11 | {{ message }}
12 |
13 |
14 |
15 |
16 |
35 |
36 |
--------------------------------------------------------------------------------
/vue05/vue5-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-06
6 |
7 |
8 |
9 |
10 | - {{ book.name }}
11 |
12 |
13 |
14 |
15 | - {{ index }} - {{ food.name }}
16 |
17 |
18 |
19 |
20 |
37 |
38 |
--------------------------------------------------------------------------------
/vue09/vue9-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-07
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
38 |
39 |
--------------------------------------------------------------------------------
/vue03/vue3-03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue3-03
6 |
7 |
8 |
9 | 姓名:{{ fullName }}
10 |
11 |
12 |
13 |
39 |
40 |
--------------------------------------------------------------------------------
/vue07/vue7-17.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-17
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
36 |
37 |
--------------------------------------------------------------------------------
/vue07/vue7-25.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-25
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
36 |
37 |
--------------------------------------------------------------------------------
/vue06/vue6-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-05
6 |
7 |
8 |
9 |
10 |
15 |
选择的是:{{ selected }}
16 |
17 |
18 |
23 |
选择的是:{{ mul }}
24 |
25 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/vue05/vue5-09.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-09
6 |
7 |
8 |
9 |
10 |
11 | - 书名:{{ book.name }}
12 | - 作者:{{ book.author }}
13 |
14 |
15 |
16 |
17 |
41 |
42 |
--------------------------------------------------------------------------------
/vue05/vue5-12.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-12
6 |
7 |
8 |
9 | 点击次数:{{ counter }}
10 |
11 |
点击增加1
12 |
13 |
14 |
点击增加1
15 |
点击增加10
16 |
17 |
18 |
39 |
40 |
--------------------------------------------------------------------------------
/vue05/shopping_trolley/shopping.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{
4 | list:[
5 | {
6 | id:1,
7 | name:'iphone',
8 | price:6000,
9 | count:1
10 | },{
11 | id:2,
12 | name:'ipad',
13 | price:2000,
14 | count:2
15 | },{
16 | id:3,
17 | name:'macbook',
18 | price:18888,
19 | count:1
20 | }
21 | ]
22 | },
23 | computed:{
24 | totalPrice:function(){
25 | var total = 0;
26 | for (var i = 0; i < this.list.length; i++) {
27 | var item = this.list[i]
28 | total += item.price * item.count
29 | }
30 | return total.toString().replace(/\B(?=(\d{3})+$)/g,',') //每三位数逗号隔开
31 | }
32 | },
33 | methods:{
34 | handleReduce:function(index){
35 | if (this.list[index].count === 1) { return }
36 | this.list[index].count --
37 | },
38 | handleAdd:function(index){
39 | this.list[index].count ++
40 | },
41 | handleRemove:function(index){
42 | this.list.splice(index,1)
43 | }
44 | }
45 | })
--------------------------------------------------------------------------------
/vue07/vue7-19.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-19
6 |
7 |
8 |
9 |
10 |
11 | 标题
12 | 底部信息
13 | 内容正文
14 | 更多内容正文
15 |
16 |
17 |
18 |
34 |
35 |
--------------------------------------------------------------------------------
/vue06/vue6-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-02
6 |
7 |
8 |
9 |
10 |
11 |
12 |
输入的内容是:{{ message }}
13 |
14 |
15 |
28 |
29 |
40 |
41 |
--------------------------------------------------------------------------------
/vue09/vue9-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-02
6 |
7 |
8 |
11 |
12 |
13 |
47 |
48 |
--------------------------------------------------------------------------------
/vue07/vue7-14.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-14
6 |
7 |
8 |
9 |
12 |
13 |
总数:{{ total }}
14 |
15 |
16 |
17 |
18 |
40 |
41 |
--------------------------------------------------------------------------------
/vue07/vue7-21.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-21
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{ props.bookName }}
14 |
15 |
16 |
17 |
18 |
43 |
44 |
--------------------------------------------------------------------------------
/vue07/vue7-15.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-15
6 |
7 |
8 |
9 |
10 | {{ message }}
11 |
12 |
13 |
14 |
15 |
42 |
43 |
--------------------------------------------------------------------------------
/vue07/vue7-28.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-28
6 |
7 |
8 |
10 |
11 |
这是一段文本
12 |
13 |
14 |
15 |
33 |
34 |
--------------------------------------------------------------------------------
/vue09/vue9-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-04
6 |
7 |
8 |
9 |
10 |
11 |
12 |
47 |
48 |
--------------------------------------------------------------------------------
/vue09/sort_form/index.js:
--------------------------------------------------------------------------------
1 | var app = new Vue({
2 | el:'#app',
3 | data:{ //key用来对应data中列内容的字段名
4 | columns:[
5 | {
6 | title:'姓名',
7 | key:'name'
8 | },
9 | {
10 | title:'年龄',
11 | key:'age',
12 | sortable:true
13 | },
14 | {
15 | title:'出生日期',
16 | key:'birthday',
17 | sortable:true
18 | },
19 | {
20 | title:'地址',
21 | key:'address'
22 | }
23 | ],
24 | data:[
25 | {
26 | name:'王小明',
27 | age:19,
28 | birthday:'1999-02-21',
29 | address:'北京市朝阳区芍药居'
30 | },
31 | {
32 | name:'张小刚',
33 | age:26,
34 | birthday:'1992-01-23',
35 | address:'北京市海淀区西二旗'
36 | },
37 | {
38 | name:'李小红',
39 | age:31,
40 | birthday:'1987-05-21',
41 | address:'北京市石景山区苹果园'
42 | },
43 | {
44 | name:'周小伟',
45 | age:27,
46 | birthday:'1991-10-10',
47 | address:'北京市丰台区王佐镇'
48 | }
49 | ]
50 | },
51 | methods:{
52 | handleAddData:function(){
53 | this.data.push({
54 | name:'刘小天',
55 | age:20,
56 | birthday:'1998-05-30',
57 | address:'北京市东城区东直门'
58 | })
59 | }
60 | }
61 | })
--------------------------------------------------------------------------------
/vue06/vue6-07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-07
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{ picked }}
13 |
{{ value }}
14 |
15 |
16 |
17 |
{{ toggle }}
18 |
{{ value1 }}
19 |
{{ value2 }}
20 |
21 |
24 | {{ selected.number }}
25 |
26 |
27 |
28 |
41 |
42 |
--------------------------------------------------------------------------------
/vue09/vue9-09.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-09
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
50 |
51 |
--------------------------------------------------------------------------------
/vue07/vue7-22.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-22
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 标题
14 | 内容正文
15 | 更多内容正文
16 | 底部信息
17 |
18 |
19 |
20 |
41 |
42 |
--------------------------------------------------------------------------------
/vue05/vue5-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-04
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
38 |
39 |
--------------------------------------------------------------------------------
/vue13/daily/src/libs/util.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | // 基本配置
3 | const Util = {
4 | imgPath:'http://127.0.0.1:8011/img/',
5 | apiPath:'http://127.0.0.1:8010/'
6 | }
7 |
8 | // ajax通用配置
9 | Util.ajax = axios.create({ //自定义配置新建一个 axios 实例
10 | baseURL:Util.apiPath
11 | })
12 |
13 | // 添加响应拦截器 在响应被 then 或 catch 处理前拦截它们。
14 | Util.ajax.interceptors.response.use(res=>{
15 | return res.data;
16 | });
17 |
18 | // 获取今天的时间戳
19 | Util.getTodayTime = function () {
20 | const date = new Date();
21 | date.setHours(0);
22 | date.setMinutes(0);
23 | date.setSeconds(0);
24 | date.setMilliseconds(0);
25 | return date.getTime();
26 | };
27 |
28 | //获取今天日期 。但在推荐列表api里日期要比真实日期多一天。所以获取今天就要加86400000
29 | Util.prevDay = function (timestamp = (new Date()).getTime()) {
30 | const date = new Date(timestamp);
31 | const year = date.getFullYear();
32 | const month = date.getMonth() + 1 < 10
33 | ? '0' + (date.getMonth() + 1)
34 | : date.getMonth() + 1;
35 | const day = date.getDate() < 10
36 | ? '0' + date.getDate()
37 | : date.getDate();
38 | return year + '' + month + '' + day;
39 | };
40 |
41 | export default Util;
--------------------------------------------------------------------------------
/vue14/shopping/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
首页
4 |
{{ count }}
5 |
6 |
7 |
{{ list }}
8 |
{{ listCount }}
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vue05/shopping_trolley/shopping.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | shopping
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | |
15 | 商品名称 |
16 | 商品单价 |
17 | 购买数量 |
18 | 操作 |
19 |
20 |
21 |
22 |
23 | | {{ index }} |
24 | {{ item.name }} |
25 | {{ item.price }} |
26 |
27 |
28 | {{item.count}}
29 |
30 | |
31 | |
32 |
33 |
34 |
35 | 总价:¥ {{ totalPrice }}
36 |
37 |
购物车为空
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/vue07/vue7-13.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-13
6 |
7 |
8 |
9 |
10 |
11 |
12 |
总数:{{ total }}
13 |
14 |
15 |
16 |
38 |
39 |
--------------------------------------------------------------------------------
/vue09/message_list/list.js:
--------------------------------------------------------------------------------
1 | Vue.component('list',{
2 | props:{
3 | list:{
4 | type:Array,
5 | default:function(){
6 | return []
7 | }
8 | }
9 | },
10 | render:function(h){
11 | var _this = this;
12 | var list = [];
13 | this.list.forEach(function( msg,index ){
14 | var node = h('div',{
15 | attrs:{
16 | class:'list-item'
17 | }
18 | },[
19 | h('span',msg.name + ':'),
20 | h('div',{
21 | attrs:{
22 | class:'list-msg'
23 | }
24 | },[
25 | h('p',msg.message),
26 | h('a',{
27 | attrs:{
28 | class:'list-reply'
29 | },
30 | on:{
31 | click:function(){
32 | _this.handleReply(index)
33 | }
34 | }
35 | },'回复')
36 | ])
37 | ])
38 | list.push(node);
39 | });
40 |
41 | if( this.list.length ){
42 | return h('div',{
43 | attrs:{
44 | class:'list'
45 | }
46 | },list);
47 | }else{
48 | return h('div',{
49 | attrs:{
50 | class:'list-nothing'
51 | }
52 | },'留言列表为空')
53 | }
54 | },
55 | methods:{
56 | // 直接向父组件(app)派发一个事件reply,父组件接收后,将当前list-item的昵称提取,并设置到v-textarea内
57 | handleReply:function(index){
58 | this.$emit('reply',index)
59 | }
60 | }
61 | })
--------------------------------------------------------------------------------
/vue07/label_page/tabs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 标签页组件
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 标签一的内容
18 | 标签一的内容
19 | 标签一的内容
20 |
21 | 标签二的内容
22 | 标签三的内容
23 |
24 |
25 | 标签1的内容
26 | 标签2的内容
27 | 标签3的内容
28 |
29 |
30 |
31 |
32 |
33 |
42 |
43 |
--------------------------------------------------------------------------------
/vue10/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --mode development --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "babel": "^6.23.0",
14 | "babel-cli": "^6.26.0",
15 | "babel-core": "^6.26.3",
16 | "babel-loader": "^7.1.5",
17 | "babel-plugin-transform-runtime": "^6.23.0",
18 | "babel-preset-env": "^1.7.0",
19 | "babel-runtime": "^6.26.0",
20 | "css-loader": "^1.0.0",
21 | "file-loader": "^2.0.0",
22 | "html-webpack-plugin": "^3.2.0",
23 | "mini-css-extract-plugin": "^0.4.2",
24 | "style-loader": "^0.22.1",
25 | "url-loader": "^1.1.1",
26 | "vue-hot-reload-api": "^2.3.0",
27 | "vue-loader": "^15.4.0",
28 | "vue-style-loader": "^4.1.2",
29 | "vue-template-compiler": "^2.5.17",
30 | "webpack": "^4.17.1",
31 | "webpack-cli": "^3.1.0",
32 | "webpack-dev-server": "^3.1.5",
33 | "webpack-merge": "^4.1.4"
34 | },
35 | "dependencies": {
36 | "vue": "^2.5.17"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/vue09/vue9-10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-10
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
46 |
47 |
--------------------------------------------------------------------------------
/vue09/message_list/input.js:
--------------------------------------------------------------------------------
1 | Vue.component('vInput',{
2 | props:{
3 | value:{
4 | type:[String,Number],
5 | default:''
6 | }
7 | },
8 | render:function(h){
9 | var _this = this;
10 | return h('div',[
11 | h('span','昵称:'),
12 | h('input',{
13 | attrs:{
14 | type:'text'
15 | },
16 | domProps:{
17 | value:this.value
18 | },
19 | on:{
20 | input:function(event){
21 | _this.value = event.target.value;
22 | _this.$emit('input',event.target.value);
23 | }
24 | }
25 | })
26 | ])
27 | }
28 | });
29 |
30 | Vue.component('vTextarea',{
31 | props:{
32 | value:{
33 | type:String,
34 | default:''
35 | }
36 | },
37 | render:function(h){
38 | var _this = this;
39 | return h('div',[
40 | h('span','留言内容'),
41 | h('textarea',{
42 | attrs:{
43 | placeholder:'请输入留言内容'
44 | },
45 | domProps:{
46 | value:this.value
47 | },
48 | ref:'message',
49 | on:{
50 | input:function(event){
51 | _this.value = event.target.value;
52 | _this.$emit('input',event.target.value);
53 | }
54 | }
55 | })
56 | ])
57 | },
58 | methods:{
59 | focus:function(){
60 | this.$refs.message.focus();
61 | }
62 | }
63 | })
--------------------------------------------------------------------------------
/vue05/vue5-10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-10
6 |
7 |
8 |
9 |
10 |
11 | - 书名:{{ book.name }}
12 | - 作者:{{ book.author }}
13 |
14 |
15 |
16 |
17 |
53 |
54 |
--------------------------------------------------------------------------------
/vue11/router/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[hash].js'
15 | },
16 | plugins:[
17 | new ExtractTextPlugin({
18 | filename:'[name].[hash].css',
19 | allChunks:true
20 | }),
21 | // new MiniCssExtractPlugin({
22 | // filename:'[name].[hash].css'
23 | // }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue11/vuex/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[hash].js'
15 | },
16 | plugins:[
17 | new ExtractTextPlugin({
18 | filename:'[name].[hash].css',
19 | allChunks:true
20 | }),
21 | // new MiniCssExtractPlugin({
22 | // filename:'[name].[hash].css'
23 | // }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue11/vue-bus/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[hash].js'
15 | },
16 | plugins:[
17 | new ExtractTextPlugin({
18 | filename:'[name].[hash].css',
19 | allChunks:true
20 | }),
21 | // new MiniCssExtractPlugin({
22 | // filename:'[name].[hash].css'
23 | // }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue13/daily/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | // const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[hash].js'
15 | },
16 | plugins:[
17 | // new ExtractTextPlugin({
18 | // filename:'[name].[hash].css',
19 | // allChunks:true
20 | // }),
21 | new MiniCssExtractPlugin({
22 | filename:'[name].[hash].css'
23 | }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue14/shopping/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | // const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[hash].js'
15 | },
16 | plugins:[
17 | // new ExtractTextPlugin({
18 | // filename:'[name].[hash].css',
19 | // allChunks:true
20 | // }),
21 | new MiniCssExtractPlugin({
22 | filename:'[name].[hash].css'
23 | }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue10/demo/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | // const ExtractTextPlugin = require('extract-text-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const merge = require('webpack-merge');
7 | const webpackBaseConfig = require('./webpack.config.js');
8 |
9 | webpackBaseConfig.plugins = [];
10 |
11 | module.exports = merge(webpackBaseConfig,{
12 | output:{
13 | publicPath:'/dist/',
14 | filename:'[name].[chunkhash].js'
15 | },
16 | plugins:[
17 | // new ExtractTextPlugin({
18 | // filename:'[name].[hash].css',
19 | // allChunks:true
20 | // }),
21 | new MiniCssExtractPlugin({
22 | filename:'[name].[chunkhash].css'
23 | }),
24 | new webpack.DefinePlugin({
25 | 'process.env':{
26 | NODE_ENV:'"production"'
27 | }
28 | }),
29 | // 压缩已经不用写UglifyJsPlugin
30 | // new webpack.optimize.UglifyJsPlugin({
31 | // compress:{
32 | // warnings:false
33 | // }
34 | // }),
35 | new HtmlWebpackPlugin({
36 | filename:'../index_prod.html',
37 | template:'./index.ejs',
38 | inject:false
39 | }),
40 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
41 | ]
42 | });
--------------------------------------------------------------------------------
/vue11/router/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'; //导入vue框架
2 | import VueRouter from 'vue-router';
3 | import App from './app.vue'; //导入app.vue组件
4 |
5 | Vue.use(VueRouter)
6 |
7 | const Routers = [
8 | //resolve在请求页面时,才去加载这个页面的js。异步实现懒加载。 使用了异步路由后,编译出的每个页面的js都叫chunk(块)
9 | //如要一次性加载,可以: component:require('.views/index.vue')
10 | {
11 | path:'/index',
12 | meta:{
13 | title:'首页'
14 | },
15 | component:(resolve) => require(['./views/index.vue'],resolve)
16 | },
17 | {
18 | path:'/about',
19 | meta:{
20 | title:'关于'
21 | },
22 | component:(resolve) => require(['./views/about.vue'],resolve)
23 | },
24 | {
25 | path:'/user/:id',
26 | meta:{
27 | title:'个人主页'
28 | },
29 | component:(resolve) => require(['./views/user.vue'],resolve)
30 | },
31 | // 当访问的路径不存在,重新定向到首页
32 | {
33 | path:'*',
34 | redirect:'/index'
35 | }
36 | ];
37 |
38 | const router = new VueRouter({
39 | //使用html的History路由模式
40 | mode:'history',
41 | routes: Routers
42 | });
43 |
44 |
45 | router.beforeEach((to,from,next)=>{
46 | //参数:即将要进入的目标的路由对象,当前导航即将要离开的路由对象,调用该方法后才能进入下一个钩子。
47 | window.document.title = to.meta.title;
48 | next(); //调用该方法才能进入下一个钩子
49 | })
50 |
51 | new Vue({
52 | el: '#app',
53 | router:router,
54 | render: h => {
55 | return h(App);
56 | }
57 | });
58 |
--------------------------------------------------------------------------------
/vue09/vue9-05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-05
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
47 |
48 |
--------------------------------------------------------------------------------
/vue09/vue9-11.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-11
6 |
7 |
8 |
9 |
10 |
11 |
12 |
51 |
52 |
--------------------------------------------------------------------------------
/vue03/vue3-02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue3-02
6 |
7 |
8 |
9 | 总价:{{ prices }}
10 |
11 |
12 |
57 |
58 |
--------------------------------------------------------------------------------
/vue14/shopping/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --mode development --history-api-fallback --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "babel": "^6.23.0",
14 | "babel-cli": "^6.26.0",
15 | "babel-core": "^6.26.3",
16 | "babel-loader": "^7.1.5",
17 | "babel-plugin-transform-runtime": "^6.23.0",
18 | "babel-preset-env": "^1.7.0",
19 | "babel-runtime": "^6.26.0",
20 | "css-loader": "^1.0.0",
21 | "file-loader": "^2.0.0",
22 | "html-webpack-plugin": "^3.2.0",
23 | "mini-css-extract-plugin": "^0.4.2",
24 | "style-loader": "^0.22.1",
25 | "url-loader": "^1.1.1",
26 | "vue-hot-reload-api": "^2.3.0",
27 | "vue-loader": "^15.4.0",
28 | "vue-style-loader": "^4.1.2",
29 | "vue-template-compiler": "^2.5.17",
30 | "webpack": "^4.17.1",
31 | "webpack-cli": "^3.1.0",
32 | "webpack-dev-server": "^3.1.5",
33 | "webpack-merge": "^4.1.4"
34 | },
35 | "dependencies": {
36 | "vue": "^2.5.17",
37 | "vue-router": "^3.0.1",
38 | "vuex": "^3.0.1"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/vue10/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'; //导入vue框架
2 | import VueRouter from 'vue-router';
3 | import App from './app.vue'; //导入app.vue组件
4 |
5 | Vue.use(VueRouter)
6 |
7 | const Routers = [
8 | //resolve在请求页面时,才去加载这个页面的js。异步实现懒加载。 使用了异步路由后,编译出的每个页面的js都叫chunk(块).如要一次性加载,可以:
9 | //import index from "./views/index.vue";
10 | // component:index
11 | //其他两个路由模仿上边的写法
12 | {
13 | path:'/index',
14 | meta:{
15 | title:'首页'
16 | },
17 | component:(resolve) => require(['./views/index.vue'],resolve)
18 | },
19 | {
20 | path:'/about',
21 | meta:{
22 | title:'关于'
23 | },
24 | component:(resolve) => require(['./views/about.vue'],resolve)
25 | },
26 | {
27 | path:'/user/:id',
28 | meta:{
29 | title:'个人主页'
30 | },
31 | component:(resolve) => require(['./views/user.vue'],resolve)
32 | },
33 | // 当访问的路径不存在,重新定向到首页
34 | {
35 | path:'*',
36 | redirect:'/index'
37 | }
38 | ];
39 |
40 | const router = new VueRouter({
41 | //使用html的History路由模式
42 | mode:'history',
43 | routes: Routers
44 | });
45 |
46 |
47 | router.beforeEach((to,from,next)=>{
48 | //参数:即将要进入的目标的路由对象,当前导航即将要离开的路由对象,调用该方法后才能进入下一个钩子。
49 | window.document.title = to.meta.title;
50 | next(); //调用该方法才能进入下一个钩子
51 | })
52 |
53 | new Vue({
54 | el: '#app',
55 | router:router,
56 | render: h => {
57 | return h(App);
58 | }
59 | });
60 |
--------------------------------------------------------------------------------
/vue11/router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --host 192.168.10.122 --mode development --history-api-fallback --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "babel": "^6.23.0",
14 | "babel-cli": "^6.26.0",
15 | "babel-core": "^6.26.3",
16 | "babel-loader": "^7.1.5",
17 | "babel-plugin-transform-runtime": "^6.23.0",
18 | "babel-preset-env": "^1.7.0",
19 | "babel-runtime": "^6.26.0",
20 | "css-loader": "^1.0.0",
21 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
22 | "file-loader": "^2.0.0",
23 | "html-webpack-plugin": "^3.2.0",
24 | "mini-css-extract-plugin": "^0.4.2",
25 | "style-loader": "^0.22.1",
26 | "url-loader": "^1.1.1",
27 | "vue-hot-reload-api": "^2.3.0",
28 | "vue-loader": "^15.4.0",
29 | "vue-style-loader": "^4.1.2",
30 | "vue-template-compiler": "^2.5.17",
31 | "webpack": "^4.17.1",
32 | "webpack-cli": "^3.1.0",
33 | "webpack-dev-server": "^3.1.5",
34 | "webpack-merge": "^4.1.4"
35 | },
36 | "dependencies": {
37 | "vue": "^2.5.17",
38 | "vue-router": "^3.0.1"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/vue05/vue5-11.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue5-11
6 |
7 |
8 |
9 |
10 |
11 |
12 | - 书名:{{ book.name }}
13 | - 作者:{{ book.author }}
14 |
15 |
16 |
17 |
18 | - 书名:{{ book.name }}
19 | - 作者:{{ book.author }}
20 |
21 |
22 |
23 |
24 |
25 |
57 |
58 |
--------------------------------------------------------------------------------
/vue06/vue6-04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue6-04
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
41 |
42 |
--------------------------------------------------------------------------------
/vue11/vuex/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --host 192.168.10.122 --mode development --history-api-fallback --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "babel": "^6.23.0",
14 | "babel-cli": "^6.26.0",
15 | "babel-core": "^6.26.3",
16 | "babel-loader": "^7.1.5",
17 | "babel-plugin-transform-runtime": "^6.23.0",
18 | "babel-preset-env": "^1.7.0",
19 | "babel-runtime": "^6.26.0",
20 | "css-loader": "^1.0.0",
21 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
22 | "file-loader": "^2.0.0",
23 | "html-webpack-plugin": "^3.2.0",
24 | "mini-css-extract-plugin": "^0.4.2",
25 | "style-loader": "^0.22.1",
26 | "url-loader": "^1.1.1",
27 | "vue-hot-reload-api": "^2.3.0",
28 | "vue-loader": "^15.4.0",
29 | "vue-style-loader": "^4.1.2",
30 | "vue-template-compiler": "^2.5.17",
31 | "webpack": "^4.17.1",
32 | "webpack-cli": "^3.1.0",
33 | "webpack-dev-server": "^3.1.5",
34 | "webpack-merge": "^4.1.4"
35 | },
36 | "dependencies": {
37 | "vue": "^2.5.17",
38 | "vue-router": "^3.0.1",
39 | "vuex": "^3.0.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vue11/vue-bus/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --host 192.168.10.122 --mode development --history-api-fallback --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "babel": "^6.23.0",
14 | "babel-cli": "^6.26.0",
15 | "babel-core": "^6.26.3",
16 | "babel-loader": "^7.1.5",
17 | "babel-plugin-transform-runtime": "^6.23.0",
18 | "babel-preset-env": "^1.7.0",
19 | "babel-runtime": "^6.26.0",
20 | "css-loader": "^1.0.0",
21 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
22 | "file-loader": "^2.0.0",
23 | "html-webpack-plugin": "^3.2.0",
24 | "mini-css-extract-plugin": "^0.4.2",
25 | "style-loader": "^0.22.1",
26 | "url-loader": "^1.1.1",
27 | "vue-hot-reload-api": "^2.3.0",
28 | "vue-loader": "^15.4.0",
29 | "vue-style-loader": "^4.1.2",
30 | "vue-template-compiler": "^2.5.17",
31 | "webpack": "^4.17.1",
32 | "webpack-cli": "^3.1.0",
33 | "webpack-dev-server": "^3.1.5",
34 | "webpack-merge": "^4.1.4"
35 | },
36 | "dependencies": {
37 | "vue": "^2.5.17",
38 | "vue-router": "^3.0.1",
39 | "vuex": "^3.0.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vue13/daily/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --mode development --open --config webpack.config.js",
8 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js",
9 | "start": "concurrently \"npm run dev\" \"node proxy.js\""
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel": "^6.23.0",
15 | "babel-cli": "^6.26.0",
16 | "babel-core": "^6.26.3",
17 | "babel-loader": "^7.1.5",
18 | "babel-plugin-transform-runtime": "^6.23.0",
19 | "babel-preset-env": "^1.7.0",
20 | "babel-runtime": "^6.26.0",
21 | "concurrently": "^4.0.1",
22 | "css-loader": "^1.0.0",
23 | "file-loader": "^2.0.0",
24 | "html-webpack-plugin": "^3.2.0",
25 | "mini-css-extract-plugin": "^0.4.2",
26 | "request": "^2.88.0",
27 | "style-loader": "^0.22.1",
28 | "url-loader": "^1.1.1",
29 | "vue-hot-reload-api": "^2.3.0",
30 | "vue-loader": "^15.4.0",
31 | "vue-style-loader": "^4.1.2",
32 | "vue-template-compiler": "^2.5.17",
33 | "webpack": "^4.17.1",
34 | "webpack-cli": "^3.1.0",
35 | "webpack-dev-server": "^3.1.5",
36 | "webpack-merge": "^4.1.4"
37 | },
38 | "dependencies": {
39 | "axios": "^0.18.0",
40 | "vue": "^2.5.17"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/vue09/vue9-01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-01
6 |
7 |
8 |
45 |
46 |
66 |
67 |
--------------------------------------------------------------------------------
/vue09/message_list/style.css:
--------------------------------------------------------------------------------
1 | *{margin: 0;padding: 0}
2 | [v-cloak]{
3 | display: none;
4 | }
5 | .message{
6 | width: 450px;
7 | text-align: right;
8 | }
9 | .message div{
10 | margin-bottom: 12px;
11 | }
12 | .message span{
13 | display: inline-block;
14 | width:100px;
15 | vertical-align: top;
16 | }
17 | .message input,.message textarea{
18 | width: 300px;
19 | height: 32px;
20 | padding: 0 6px;
21 | color:#657180;
22 | border:1px solid #d7dde4;
23 | border-radius: 4px;
24 | cursor:text;
25 | outline: none;
26 | }
27 | .message input:focus, .message textarea:focus{
28 | border: 1px solid #3399ff;
29 | }
30 | .message textarea{
31 | height: 60px;
32 | padding: 4px 6px;
33 | }
34 | .message button{
35 | display: inline-block;
36 | padding: 6px 15px;
37 | border: 1px solid #39f;
38 | border-radius:4px;
39 | color:#fff;
40 | background-color: #39f;
41 | cursor: pointer;
42 | outline:none;
43 | }
44 | .list{
45 | margin-top: 50px;
46 | }
47 | .list-item{
48 | padding: 10px;
49 | border-bottom: 1px solid #e3e8ee;
50 | overflow: hidden;
51 | }
52 | .list-item span{
53 | display: block;
54 | width: 70px;
55 | float:left;
56 | color: #39f;
57 | }
58 | .list-msg{
59 | display:block;
60 | margin-left: 60px;
61 | text-align: justify;
62 | }
63 | .list-msg a{
64 | color: #9ea7b4;
65 | cursor: pointer;
66 | float:right;
67 | }
68 | .list-msg a:hover{
69 | color:#39f;
70 | }
71 | .list-nothing{
72 | text-align: center;
73 | color:#9ea7b4;
74 | padding: 20px;
75 | }
--------------------------------------------------------------------------------
/vue11/vuex/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
首页
4 | {{ count }}
5 |
6 |
7 |
8 |
9 |
{{ list }}
10 |
{{ listCount }}
11 |
通过this.$store.state.moduleA.useName 获取的module.js文件中的数据{{ username }}
12 |
sumCount里count为10,加上count默认是0。初始是10+0的结果:{{ samCount }}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/vue02/vue2-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue2-06
6 |
7 |
8 |
9 | {{ date | formatDate }}
10 |
16 |
17 |
18 |
52 |
53 |
--------------------------------------------------------------------------------
/vue07/vue7-12.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue7-12
6 |
7 |
8 |
9 |
10 |
11 |
12 |
总数:{{ total }}
13 |
14 |
15 |
16 |
17 |
48 |
49 |
--------------------------------------------------------------------------------
/vue09/vue9-06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-06
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
63 |
64 |
--------------------------------------------------------------------------------
/vue13/daily/proxy.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const request = require('request');
3 |
4 | const hostname = '127.0.0.1';
5 | const port = 8010;
6 | const imgPort = 8011;
7 |
8 | // 创建一个API 代理服务器
9 | const apiServer = http.createServer((req, res) => {
10 | const url = 'http://news-at.zhihu.com/api/4' + req.url;
11 | const options = {
12 | url: url
13 | };
14 |
15 | function callback (error, response, body) {
16 | if (!error && response.statusCode === 200) {
17 | // 设置编码类型,否则中文会显示为乱码
18 | res.setHeader('Content-Type', 'text/plain;charset=UTF-8');
19 | // 设置所有域允许跨域
20 | res.setHeader('Access-Control-Allow-Origin', '*');
21 | // 返回代理后的内容
22 | res.end(body);
23 | }
24 | }
25 | request.get(options, callback);
26 | });
27 |
28 | // 监听8010端口
29 | apiServer.listen(port, hostname, () => {
30 | console.log(`接口代理运行在 http://${hostname}:${port}/`);
31 | });
32 |
33 | // 创建一个图片代理服务
34 | const imgServer = http.createServer((req, res) => {
35 | const url = req.url.split('/img/')[1];
36 | const options = {
37 | url: url,
38 | encoding: null
39 | };
40 |
41 | function callback (error, response, body) {
42 | if (!error && response.statusCode === 200) {
43 | const contentType = response.headers['content-type'];
44 | res.setHeader('Content-Type', contentType);
45 | res.setHeader('Access-Control-Allow-Origin', '*');
46 | res.end(body);
47 | }
48 | }
49 | request.get(options, callback);
50 | });
51 |
52 | // 监听8011端口
53 | imgServer.listen(imgPort,hostname,()=>{
54 | console.log(`图片代理运行在http://${hostname}:${imgPort}/`);
55 | })
--------------------------------------------------------------------------------
/vue13/daily/src/components/daily-article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ data.title }}
4 |
5 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/vue11/vue-bus/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
首页
4 | {{ count }}
5 |
6 |
7 |
8 |
9 |
{{ list }}
10 |
{{ listCount }}
11 |
通过this.$store.state.moduleA.useName 获取的module.js文件中的数据{{ username }}
12 |
sumCount里count为10,加上count默认是0。初始是10+0的结果:{{ samCount }}
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/vue08/v-time/time.js:
--------------------------------------------------------------------------------
1 | var Time = {
2 | // 获取当前时间戳
3 | getUnix:function(){
4 | var date = new Date();
5 | return date.getTime();
6 | },
7 | // 获取今天0点0分0秒的时间戳
8 | getTodayUnix:function(){
9 | var date = new Date();
10 | date.setHours(0); //设置指定时间的小时字段
11 | date.setMinutes(0);
12 | date.setSeconds(0);
13 | date.setMilliseconds(0);
14 | return date.getTime();
15 | },
16 | // 获取今年1月1日0点0分0秒的时间戳
17 | getYearUnix:function(){
18 | var date = new Date();
19 | date.setMonth(0)
20 | date.setDate(1);
21 | date.setHours(0);
22 | date.setMinutes(0);
23 | date.setSeconds(0);
24 | date.setMilliseconds(0);
25 | return date.getTime();
26 | },
27 | // 获取标准年月日
28 | getLastDate:function(time){
29 | var date = new Date(time);
30 | var month = date.getMonth() + 1 < 10 ? '0' + ( date.getMonth() + 1 ) : date.getMonth() + 1;
31 | var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
32 | return date.getFullYear() + '-' + month + '-' + day
33 | },
34 | // 转换时间
35 | getFormatTime:function(timestamp){
36 | var now = this.getUnix(); //当前时间戳
37 | var today = this.getTodayUnix(); //今天0点时间戳
38 | var year = this.getYearUnix(); //今年0点时间戳
39 | var timer = ( now - timestamp ) / 1000; //转化为秒级时间戳
40 | var tip = '';
41 |
42 | // 1分钟以前,显示“刚刚”。
43 | // 1分钟~1小时之间,显示“xx分钟前”。
44 | // 1小时~1天之间,显示“xx小时前”。
45 | // 1天~1个月(31天)之间,显示“xx天前”。
46 | // 大于1个月,显示“xx年xx月xx日”。
47 |
48 | if( timer <= 0 ){
49 | tip = '刚刚';
50 | }else if( Math.floor( timer / 60 ) <= 0 ){
51 | tip = '刚刚'
52 | }else if( timer < 3600 ){
53 | tip = Math.floor( timer / 60 ) + '分钟前';
54 | }else if( timer >= 3600 && ( timestamp - today >= 0 ) ){
55 | tip = Math.floor( timer/3600 ) + '小时前'
56 | }else if( timer/86400 <=31 ){
57 | tip = Math.ceil( timer/86400 ) + '天前'
58 | }else{
59 | tip = this.getLastDate(timestamp);
60 | }
61 | return tip;
62 | }
63 | }
64 |
65 | Vue.directive('time',{
66 | bind:function( el,binding ){
67 | el.innerHTML = Time.getFormatTime( binding.value );
68 | el.__timeout__ = setInterval(function(){
69 | el.innerHTML = Time.getFormatTime( binding.value );
70 | },60000)
71 | },
72 | unbind:function(el){
73 | clearInterval( el.__timeout__ );
74 | delete el.__timeout__;
75 | }
76 | })
--------------------------------------------------------------------------------
/vue10/demo/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | // var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | const config = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | module:{
18 | rules:[
19 | {
20 | test:/\.vue$/,
21 | loader:'vue-loader',
22 | options:{
23 | loaders:{
24 | css:[
25 | 'vue-style-loader',
26 | 'mini-css-extract-plugin',
27 | 'css-loader'
28 | ]
29 | }
30 | }
31 | },
32 | {
33 | test: /\.css$/,
34 | use:[ //数组形式的话,编译是从后往前。
35 | MiniCssExtractPlugin.loader,
36 | 'css-loader'
37 | ]
38 | },
39 | // {
40 | // test:/\.vue$/,
41 | // loader:'vue-loader',
42 | // options:{
43 | // loaders:{
44 | // css:ExtractTextPlugin.extract({
45 | // use:'css-loader',
46 | // fallback:'vue-style-loader'
47 | // })
48 | // }
49 | // }
50 | // },
51 | // {
52 | // test: /\.css$/,
53 | // use: ExtractTextPlugin.extract({
54 | // use: 'css-loader',
55 | // fallback: 'style-loader'
56 | // })
57 | // },
58 | // 除非您要自定义 entry point(入口点) ,否则无需指定babel-loader。
59 | // {
60 | // test:/\.js$/,
61 | // loader:'babel-loader',
62 | // exclude:/node_modules/
63 | // },
64 | {
65 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
66 | loader:'url-loader?limit=1024' //文件小于1k就以base64形式加载
67 | }
68 | ]
69 | },
70 | plugins:[
71 | // new ExtractTextPlugin({
72 | // filename:'main.css',//重命名提取后的css文件
73 | // allChunks: true //有了chunk,需要在此配置
74 | // }),
75 | new MiniCssExtractPlugin('main.css'),
76 | // new ExtractTextPlugin("main.css"),
77 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
78 | ]
79 | };
80 | module.exports = config
81 | //ES6: export default config
--------------------------------------------------------------------------------
/vue13/daily/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | // var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | const config = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | module:{
18 | rules:[
19 | {
20 | test:/\.vue$/,
21 | loader:'vue-loader',
22 | options:{
23 | loaders:{
24 | css:[
25 | 'vue-style-loader',
26 | 'mini-css-extract-plugin',
27 | 'css-loader'
28 | ]
29 | }
30 | }
31 | },
32 | {
33 | test: /\.css$/,
34 | use:[ //数组形式的话,编译是从后往前。
35 | MiniCssExtractPlugin.loader,
36 | 'css-loader'
37 | ]
38 | },
39 | // {
40 | // test:/\.vue$/,
41 | // loader:'vue-loader',
42 | // options:{
43 | // loaders:{
44 | // css:ExtractTextPlugin.extract({
45 | // use:'css-loader',
46 | // fallback:'vue-style-loader'
47 | // })
48 | // }
49 | // }
50 | // },
51 | // {
52 | // test: /\.css$/,
53 | // use: ExtractTextPlugin.extract({
54 | // use: 'css-loader',
55 | // fallback: 'style-loader'
56 | // })
57 | // },
58 | // 除非您要自定义 entry point(入口点) ,否则无需指定babel-loader。
59 | // {
60 | // test:/\.js$/,
61 | // loader:'babel-loader',
62 | // exclude:/node_modules/
63 | // },
64 | {
65 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
66 | loader:'url-loader?limit=1024' //文件小于1k就以base64形式加载
67 | }
68 | ]
69 | },
70 | plugins:[
71 | // new ExtractTextPlugin({
72 | // filename:'main.css',//重命名提取后的css文件
73 | // allChunks: true //有了chunk,需要在此配置
74 | // }),
75 | new MiniCssExtractPlugin('main.css'),
76 | // new ExtractTextPlugin("main.css"),
77 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
78 | ]
79 | };
80 | module.exports = config
81 | //ES6: export default config
--------------------------------------------------------------------------------
/vue14/shopping/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | // var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | const config = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | module:{
18 | rules:[
19 | {
20 | test:/\.vue$/,
21 | loader:'vue-loader',
22 | options:{
23 | loaders:{
24 | css:[
25 | 'vue-style-loader',
26 | 'mini-css-extract-plugin',
27 | 'css-loader'
28 | ]
29 | }
30 | }
31 | },
32 | {
33 | test: /\.css$/,
34 | use:[ //数组形式的话,编译是从后往前。
35 | MiniCssExtractPlugin.loader,
36 | 'css-loader'
37 | ]
38 | },
39 | // {
40 | // test:/\.vue$/,
41 | // loader:'vue-loader',
42 | // options:{
43 | // loaders:{
44 | // css:ExtractTextPlugin.extract({
45 | // use:'css-loader',
46 | // fallback:'vue-style-loader'
47 | // })
48 | // }
49 | // }
50 | // },
51 | // {
52 | // test: /\.css$/,
53 | // use: ExtractTextPlugin.extract({
54 | // use: 'css-loader',
55 | // fallback: 'style-loader'
56 | // })
57 | // },
58 | // 除非您要自定义 entry point(入口点) ,否则无需指定babel-loader。
59 | // {
60 | // test:/\.js$/,
61 | // loader:'babel-loader',
62 | // exclude:/node_modules/
63 | // },
64 | {
65 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
66 | loader:'url-loader?limit=1024' //文件小于1k就以base64形式加载
67 | }
68 | ]
69 | },
70 | plugins:[
71 | // new ExtractTextPlugin({
72 | // filename:'main.css',//重命名提取后的css文件
73 | // allChunks: true //有了chunk,需要在此配置
74 | // }),
75 | new MiniCssExtractPlugin('main.css'),
76 | // new ExtractTextPlugin("main.css"),
77 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
78 | ]
79 | };
80 | module.exports = config
81 | //ES6: export default config
--------------------------------------------------------------------------------
/vue13/daily/src/directives/time.js:
--------------------------------------------------------------------------------
1 | var Time = {
2 | // 获取当前时间戳
3 | getUnix: function () {
4 | var date = new Date();
5 | return date.getTime();
6 | },
7 | // 获取今天0点0分0秒的时间戳
8 | getTodayUnix: function () {
9 | var date = new Date();
10 | date.setHours(0);
11 | date.setMinutes(0);
12 | date.setSeconds(0);
13 | date.setMilliseconds(0);
14 | return date.getTime();
15 | },
16 | // 获取今年1月1日0点0分0秒的时间戳
17 | getYearUnix: function () {
18 | var date = new Date();
19 | date.setMonth(0);
20 | date.setDate(1);
21 | date.setHours(0);
22 | date.setMinutes(0);
23 | date.setSeconds(0);
24 | date.setMilliseconds(0);
25 | return date.getTime();
26 | },
27 | // 获取标准年月日
28 | getLastDate: function(time) {
29 | var date = new Date(time);
30 | var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
31 | var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
32 | return date.getFullYear() + '-' + month + "-" + day;
33 | },
34 | // 转换时间
35 | getFormatTime: function(timestamp) {
36 | var now = this.getUnix(); //当前时间戳
37 | var today = this.getTodayUnix(); //今天0点时间戳
38 | var year = this.getYearUnix(); //今年0点时间戳
39 | var timer = (now - timestamp) / 1000; // 转换为秒级时间戳
40 | var tip = '';
41 |
42 | if (timer <= 0) {
43 | tip = '刚刚';
44 | } else if (Math.floor(timer/60) <= 0) {
45 | tip = '刚刚';
46 | } else if (timer < 3600) {
47 | tip = Math.floor(timer/60) + '分钟前';
48 | } else if (timer >= 3600 && (timestamp - today >= 0) ) {
49 | tip = Math.floor(timer/3600) + '小时前';
50 | } else if (timer/86400 <= 31) {
51 | tip = Math.ceil(timer/86400) + '天前';
52 | } else {
53 | tip = this.getLastDate(timestamp);
54 | }
55 | return tip;
56 | }
57 | };
58 |
59 | export default {
60 | bind: function (el, binding) {
61 | el.innerHTML = Time.getFormatTime(binding.value * 1000);
62 | el.__timeout__ = setInterval(function() {
63 | el.innerHTML = Time.getFormatTime(binding.value * 1000);
64 | }, 60000);
65 | },
66 | unbind: function (el) {
67 | clearInterval(el.__timeout__);
68 | delete el.__timeout__;
69 | }
70 | }
--------------------------------------------------------------------------------
/vue11/vuex/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | module.exports = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | // optimization: {
18 | // splitChunks: {
19 | // cacheGroups: {
20 | // styles: {
21 | // name: 'main',
22 | // test: /\.css$/,
23 | // chunks: 'all', // merge all the css chunk to one file
24 | // enforce: true
25 | // }
26 | // }
27 | // }
28 | // },
29 | plugins:[
30 | new ExtractTextPlugin({
31 | filename:'main.css',//重命名提取后的css文件
32 | allChunks: true //有了chunk,需要在此配置
33 | }),
34 | // new MiniCssExtractPlugin({
35 | // filename:'main.css',
36 | // }),
37 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
38 | ],
39 | module:{
40 | rules:[
41 | // {
42 | // test:/\.vue$/,
43 | // loader:'vue-loader',
44 | // options:{
45 | // loaders:{
46 | // css:[
47 | // 'vue-style-loader',
48 | // 'mini-css-extract-plugin',
49 | // 'css-loader'
50 | // ]
51 | // }
52 | // }
53 | // },
54 | // {
55 | // test: /\.css$/,
56 | // use:[ //数组形式的话,编译是从后往前。
57 | // MiniCssExtractPlugin.loader,
58 | // 'css-loader'
59 | // ]
60 | // },
61 | {
62 | test:/\.vue$/,
63 | loader:'vue-loader',
64 | options:{
65 | loaders:{
66 | css:ExtractTextPlugin.extract({
67 | use:'css-loader',
68 | fallback:'vue-style-loader'
69 | })
70 | }
71 | }
72 | },
73 | {
74 | test: /\.css$/,
75 | use: ExtractTextPlugin.extract({
76 | use: 'css-loader',
77 | fallback: 'style-loader'
78 | })
79 | },
80 | {
81 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
82 | loader:'url-loader?limit=1024'
83 | }
84 | ]
85 | }
86 |
87 | };
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 《Vue.js实战》 笔记
2 |
3 | ## 项目起源
4 | 最近有时间研读了Aresn的《Vue.js实战》一书,收获颇丰。感觉是学习Vue的书籍里比较好的一本书了。在此做些笔记备忘。
5 |
6 | 关于本书 中有说明,示例代码已经存放在了[github](https://github.com/icarusion/vue-book)上,里边有购买途径和已知勘误。但进去发现代码是从"实战篇"开始有的。"基础篇"和"晋级篇"的代码并没有。
7 | 大胆猜测没有的原因一个是因为前期并没有结合前端工程化,代码还比较简单。另一个就是作者希望我们能自己敲一遍代码,加深对Vue的学习。 但对于Vue新手,甚至是前端新手,有时可能还是需要全部代码的。所以在笔记中加入了书中几乎所有代码供有需要的参考。另随着时间的迁移,或许有些技术点会发生改变,书中以webpack2为例。笔记项目中采用webpack4可直接npm install 跑通后几章代码。但毕竟一人精力和能力有限。所以有了这个GitHub项目。我们可以通过协作的方式来共同维护这个项目。Git的历史记录也可以见证前端行业的一些变迁。
8 |
9 | ## 项目目录结构
10 | + vue-combat-book ----- Vue.js实战
11 | + vue01 ----- 初识vue.js
12 | + vue02 ----- 数据绑定
13 | + vue03 ----- 计算属性
14 | + vue04 ----- v-bind及class与style绑定
15 | + vue05 ----- 基本指令
16 | + shopping_trolley ----- 开发购物车小功能
17 | + vue06 ----- 表单域v-model
18 | + vue07 ----- 组件详解
19 | + label_page ----- 标签页组件
20 | + input_box ----- 数字输入框组件
21 | + vue08 ----- 自定义指令
22 | + menu ----- 从外部关闭的下拉菜单
23 | + v-time ----- 开发实时时间转换v-time
24 | + vue09 ----- render函数
25 | + sort_form ----- 可排序表格组件
26 | + message_list ----- 留言列表
27 | + vue10 ----- 使用webpack
28 | + demo ----- demo代码
29 | + README10 ----- 第十章笔记
30 | + vue11 ----- 插件
31 | + router ----- router代码
32 | + vuex ----- vuex代码
33 | + vue-bus ----- vue-bus代码
34 | + README11 ----- 第十一章笔记
35 | + vue12 ----- iView经典组件剖析
36 | + README12 ----- 第十二章笔记
37 | + vue13 ----- 知乎日报项目开发
38 | + daily ----- daily代码
39 | + README13 ----- 第十三章笔记
40 | + vue14 ----- 电商网站项目开发
41 | + shopping ----- shopping代码
42 | + vue15 ----- 相关开源项目介绍
43 | +README15 ----- 第十五章笔记
44 | + README ----- 项目介绍
45 |
46 | ## 项目文件百度网盘
47 |
48 | ~~[项目代码 + 《Vue.js实战》电子版zip](https://pan.baidu.com/s/1tSWJceedc27EnfET5IX_xg)~~
49 | 书籍电子版已删除,[项目代码](https://pan.baidu.com/s/1tSWJceedc27EnfET5IX_xg)
50 | PS:强烈建议购买正版书阅读,另外对着屏幕总是比看书费眼睛吧。
51 |
52 | 2018/11.01更新:
53 | 修改vue01-vue10部分文件代码
54 | [新增vue-devtools工具](https://pan.baidu.com/s/1tSWJceedc27EnfET5IX_xg),如何安装有人写的文章很清楚了,[戳这里](https://segmentfault.com/a/1190000009682735)
55 | [新增简单的在webpack4.23.1下对vue2.5.17的搭建](https://github.com/zyf711/webpack-quick)
56 |
57 | 2018/11.13更新:
58 | [新增vue+vue-router+vuex做的移动端小答题页面](https://github.com/zyf711/vue2-answer)
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/vue14/shopping/src/components/product.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ info.name }}
6 | 销量:{{ info.sales }}
7 |
8 | ¥ {{ info.cost }}
9 | 加入购物车
10 |
11 |
12 |
13 |
35 |
--------------------------------------------------------------------------------
/vue14/shopping/src/product.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | id: 1,
4 | name: 'AirPods',
5 | brand: 'Apple',
6 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/1.jpeg',
7 | sales: 10000,
8 | cost: 1288,
9 | color: '白色'
10 | },
11 | {
12 | id: 2,
13 | name: 'BeatsX 入耳式耳机',
14 | brand: 'Beats',
15 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/2.jpeg',
16 | sales: 11000,
17 | cost: 1188,
18 | color: '白色'
19 | },
20 | {
21 | id: 3,
22 | name: 'Beats Solo3 Wireless 头戴式式耳机',
23 | brand: 'Beats',
24 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/3.jpeg',
25 | sales: 5000,
26 | cost: 2288,
27 | color: '金色'
28 | },
29 | {
30 | id: 4,
31 | name: 'Beats Pill+ 便携式扬声器',
32 | brand: 'Beats',
33 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/4.jpeg',
34 | sales: 3000,
35 | cost: 1888,
36 | color: '红色'
37 | },
38 | {
39 | id: 5,
40 | name: 'Sonos PLAY:1 无线扬声器',
41 | brand: 'Sonos',
42 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/5.jpeg',
43 | sales: 8000,
44 | cost: 1578,
45 | color: '白色'
46 | },
47 | {
48 | id: 6,
49 | name: 'Powerbeats3 by Dr. Dre Wireless 入耳式耳机',
50 | brand: 'Beats',
51 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/6.jpeg',
52 | sales: 12000,
53 | cost: 1488,
54 | color: '金色'
55 | },
56 | {
57 | id: 7,
58 | name: 'Beats EP 头戴式耳机',
59 | brand: 'Beats',
60 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/7.jpeg',
61 | sales: 25000,
62 | cost: 788,
63 | color: '蓝色'
64 | },
65 | {
66 | id: 8,
67 | name: 'B&O PLAY BeoPlay A1 便携式蓝牙扬声器',
68 | brand: 'B&O',
69 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/8.jpeg',
70 | sales: 15000,
71 | cost: 1898,
72 | color: '金色'
73 | },
74 | {
75 | id: 9,
76 | name: 'Bose® QuietComfort® 35 无线耳机',
77 | brand: 'Bose',
78 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/9.jpeg',
79 | sales: 14000,
80 | cost: 2878,
81 | color: '蓝色'
82 | },
83 | {
84 | id: 10,
85 | name: 'B&O PLAY Beoplay H4 无线头戴式耳机',
86 | brand: 'B&O',
87 | image: 'http://ordfm6aah.bkt.clouddn.com/shop/10.jpeg',
88 | sales: 9000,
89 | cost: 2298,
90 | color: '金色'
91 | }
92 | ]
--------------------------------------------------------------------------------
/vue11/vuex/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueRouter from 'vue-router';
3 | import Vuex from 'vuex';
4 | import App from './app.vue';
5 | import moduleA from './moduleA' //vuex中modules分割出的模块
6 |
7 | Vue.use(VueRouter)
8 | Vue.use(Vuex)
9 |
10 | const Routers = [
11 | {
12 | path:'/index',
13 | meta:{
14 | title:'首页'
15 | },
16 | component:(resolve) => require(['./views/index.vue'],resolve)
17 | },
18 | {
19 | path:'/about',
20 | meta:{
21 | title:'关于'
22 | },
23 | component:(resolve) => require(['./views/about.vue'],resolve)
24 | },
25 | {
26 | path:'/user/:id',
27 | meta:{
28 | title:'个人主页'
29 | },
30 | component:(resolve) => require(['./views/user.vue'],resolve)
31 | },
32 | {
33 | path:'*',
34 | redirect:'/index'
35 | }
36 | ];
37 |
38 | const router = new VueRouter({
39 | mode:'history',
40 | routes: Routers
41 | });
42 |
43 |
44 | router.beforeEach((to,from,next)=>{
45 | window.document.title = to.meta.title;
46 | next();
47 | })
48 |
49 | const store = new Vuex.Store({
50 | modules:{ moduleA:moduleA }, // 项目足够大,store内容过多时,modules把store里内容写到不同文件中
51 | state:{ //数据保存在state字段内
52 | count:0, //任何组件通过this.$store.state.count读取
53 | list:[1,5,8,10,30,50]
54 | },
55 | mutations:{ //mutations改变state字段数据唯一途径
56 | increment(state){
57 | state.count ++ ; //任何组件通过this.$store.commit('increment')提交事件名
58 | },
59 | decrease(state,n=10){// mutations可以接受第二个参数,数字,字符串或对象等类型
60 | state.count -= n;
61 | },
62 | custom(state,params){
63 | state.count += params.count;
64 | }
65 | },
66 | actions:{ //actions提交的是mutations
67 | //涉及改变数据的就用mutations,存在业务逻辑的就用actions,actions可以异步操作业务逻辑。
68 | asyncIncrement(context){ //任何组件this.$store.dispatch('asyncIncrement')触发
69 | return new Promise((resolve,reject) => { //Promise在2秒后提交mutations
70 | setTimeout(()=>{
71 | const random = Math.random();
72 | if( random >.5 ){
73 | context.commit('increment');
74 | console.log(random)
75 | resolve();
76 | }else{
77 | reject(random)
78 | }
79 | },2000)
80 | });
81 | }
82 | },
83 | getters:{
84 | filteredList:state => {
85 | return state.list.filter(item => item < 10); //任何组件通过this.$store.getters.filteredList提交事件名
86 | },
87 | listCount:(state,getters) => {
88 | return getters.filteredList.length;
89 | }
90 | }
91 | })
92 |
93 | new Vue({
94 | el: '#app',
95 | router:router,
96 | store:store,
97 | render: h => {
98 | return h(App);
99 | }
100 | });
--------------------------------------------------------------------------------
/vue07/label_page/tabs.js:
--------------------------------------------------------------------------------
1 | Vue.component('tabs',{
2 | template:'\
3 |
\
4 |
{{item.label}}
\
5 |
\
6 |
\
7 | \
8 |
\
9 |
', //上边的slot是嵌套的pane
10 | props:{
11 | // 这里value为了可以使用v-model
12 | value:{
13 | type:[String,Number]
14 | }
15 | },
16 | data:function(){
17 | return {
18 | currentValue:this.value, // 因为不能修改value,所以复制一份自己维护
19 | navList:[] //用于渲染tabs的标题
20 | }
21 | },
22 | methods:{
23 | tabCls:function(item){
24 | return [
25 | 'tabs-tab',
26 | {
27 | // 给当前选中的tab,也就是item.name === this.currentValue为true的加一个class
28 | // 运算优先级=== 高于 条件:
29 | // 运算符优先级https://www.cnblogs.com/yy-hh/p/4624792.html
30 | 'tabs-tab-active':item.name === this.currentValue
31 | }
32 | ]
33 | },
34 | getTabs(){ // 通过遍历子组件,得到所有的pane组件
35 | return this.$children.filter(function(item){
36 | return item.$options.name === 'pane'
37 | });
38 | },
39 | updateNav(){ //更新标题
40 | this.navList = [];
41 | var _this = this;
42 | // 把pane的label和name提取出来,构成一个object并添加到数组navList里,后面会在template里用到
43 | this.getTabs().forEach(function( pane,index ){
44 | _this.navList.push({
45 | label:pane.label,
46 | name:pane.name || index
47 | });
48 | // 如果没给pane设置name,(比如没给activeKey1设置初始选中哪个)默认设置它的索引
49 | if( !pane.name ) pane.name = index;
50 | // 设置当前选中的tab的索引,在此就是默认第一个显示
51 | if( index === 0 ){
52 | if( !_this.currentValue ){
53 | _this.currentValue = pane.name || index;
54 | }
55 | }
56 | });
57 | this.updateStatus()
58 | },
59 | updateStatus(){ // 显示当前选中的tab对应的pane组件,隐藏没选中的
60 | var tabs = this.getTabs();
61 | var _this = this;
62 | tabs.forEach(function (tab){
63 | // 这里是对所有pane里边的sw判断是true还是false
64 | // 运算优先级=== 高于= 先判断tab.name === _this.currentValue 是true还是false,再赋值给tab.sw
65 | return tab.sw = tab.name === _this.currentValue;
66 | })
67 | },
68 | handleChange:function(index){ //点击tab标题时触发
69 | var nav = this.navList[index];
70 | var name = nav.name;
71 | // 改变当前选中的tab,并触发下面的watch
72 | this.currentValue = name;
73 | // 更新value
74 | this.$emit('input',name);
75 | // 触发一个自定义事件,供父级使用
76 | this.$emit('on-click',name);
77 | }
78 | },
79 | watch:{
80 | value:function(val){
81 | this.currentValue = val;
82 | },
83 | currentValue:function(){
84 | // 在当前选中的tab发生变化时,更新pane的显示状态
85 | this.updateStatus()
86 | }
87 | }
88 | })
--------------------------------------------------------------------------------
/vue11/router/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | module.exports = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | // optimization: {
18 | // splitChunks: {
19 | // cacheGroups: {
20 | // styles: {
21 | // name: 'main',
22 | // test: /\.css$/,
23 | // chunks: 'all', // merge all the css chunk to one file
24 | // enforce: true
25 | // }
26 | // }
27 | // }
28 | // },
29 | plugins:[
30 | new ExtractTextPlugin({
31 | filename:'main.css',//重命名提取后的css文件
32 | allChunks: true //有了chunk,需要在此配置
33 | }),
34 | // new MiniCssExtractPlugin({
35 | // filename:'main.css',
36 | // }),
37 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
38 | ],
39 | module:{
40 | rules:[
41 | // {
42 | // test:/\.vue$/,
43 | // loader:'vue-loader',
44 | // options:{
45 | // loaders:{
46 | // css:[
47 | // 'vue-style-loader',
48 | // 'mini-css-extract-plugin',
49 | // 'css-loader'
50 | // ]
51 | // }
52 | // }
53 | // },
54 | // {
55 | // test: /\.css$/,
56 | // use:[ //数组形式的话,编译是从后往前。
57 | // MiniCssExtractPlugin.loader,
58 | // 'css-loader'
59 | // ]
60 | // },
61 | {
62 | test:/\.vue$/,
63 | loader:'vue-loader',
64 | options:{
65 | loaders:{
66 | css:ExtractTextPlugin.extract({
67 | use:'css-loader',
68 | fallback:'vue-style-loader'
69 | })
70 | }
71 | }
72 | },
73 | {
74 | test: /\.css$/,
75 | use: ExtractTextPlugin.extract({
76 | use: 'css-loader',
77 | fallback: 'style-loader'
78 | })
79 | },
80 | // {
81 | // test:/\.js$/,
82 | // loader:'babel-loader',
83 | // exclude:/node_modules/
84 | // },
85 | {
86 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
87 | loader:'url-loader?limit=1024'
88 | }
89 | ]
90 | }
91 |
92 | };
--------------------------------------------------------------------------------
/vue11/vue-bus/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueRouter from 'vue-router';
3 | import Vuex from 'vuex';
4 | import App from './app.vue';
5 | import moduleA from './moduleA' //vuex中modules分割出的模块
6 | import VueBus from './vue-bus';
7 |
8 | Vue.use(VueRouter);
9 | Vue.use(Vuex);
10 | Vue.use(VueBus);
11 |
12 | const Routers = [
13 | {
14 | path:'/index',
15 | meta:{
16 | title:'首页'
17 | },
18 | component:(resolve) => require(['./views/index.vue'],resolve)
19 | },
20 | {
21 | path:'/about',
22 | meta:{
23 | title:'关于'
24 | },
25 | component:(resolve) => require(['./views/about.vue'],resolve)
26 | },
27 | {
28 | path:'/user/:id',
29 | meta:{
30 | title:'个人主页'
31 | },
32 | component:(resolve) => require(['./views/user.vue'],resolve)
33 | },
34 | {
35 | path:'*',
36 | redirect:'/index'
37 | }
38 | ];
39 |
40 | const router = new VueRouter({
41 | mode:'history',
42 | routes: Routers
43 | });
44 |
45 |
46 | router.beforeEach((to,from,next)=>{
47 | window.document.title = to.meta.title;
48 | next();
49 | })
50 |
51 | const store = new Vuex.Store({
52 | modules:{ moduleA:moduleA }, // 项目足够大,store内容过多时,modules把store里内容写到不同文件中
53 | state:{ //数据保存在state字段内
54 | count:0, //任何组件通过this.$store.state.count读取
55 | list:[1,5,8,10,30,50]
56 | },
57 | mutations:{ //mutations改变state字段数据唯一途径
58 | increment(state){
59 | state.count ++ ; //任何组件通过this.$store.commit('increment')提交事件名
60 | },
61 | decrease(state,n=10){// mutations可以接受第二个参数,数字,字符串或对象等类型
62 | state.count -= n;
63 | },
64 | custom(state,params){
65 | state.count += params.count;
66 | }
67 | },
68 | actions:{ //actions提交的是mutations
69 | //涉及改变数据的就用mutations,存在业务逻辑的就用actions,actions可以异步操作业务逻辑。
70 | asyncIncrement(context){ //任何组件this.$store.dispatch('asyncIncrement')触发
71 | return new Promise((resolve,reject) => { //Promise在2秒后提交mutations
72 | setTimeout(()=>{
73 | const random = Math.random();
74 | if( random >.5 ){
75 | context.commit('increment');
76 | console.log(random)
77 | resolve();
78 | }else{
79 | reject(random)
80 | }
81 | },2000)
82 | });
83 | }
84 | },
85 | getters:{
86 | filteredList:state => {
87 | return state.list.filter(item => item < 10); //任何组件通过this.$store.getters.filteredList提交事件名
88 | },
89 | listCount:(state,getters) => {
90 | return getters.filteredList.length;
91 | }
92 | }
93 | })
94 |
95 | new Vue({
96 | el: '#app',
97 | router:router,
98 | store:store,
99 | render: h => {
100 | return h(App);
101 | }
102 | });
--------------------------------------------------------------------------------
/vue11/vue-bus/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | // const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const { VueLoaderPlugin } = require('vue-loader'); //vue-loader,15的版本需要再添加plugin的配置
4 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
5 |
6 | module.exports = {
7 | //配置的单入口,webpack从index.js开始工作,webpack4默认entry 路径./src/index.js
8 | // 所以下边的entry可以不写
9 | // entry:{
10 | // main:'./src/index'
11 | // },
12 | output:{//打包后的文件会存储为demo/dist/main.js 在html中引用它就可以了
13 | path:path.join(__dirname,'./dist'), //打包后文件的输出目录
14 | publicPath:'/dist/', //指定资源文件引用目录,可以是CDN
15 | filename:'main.js' //输出文件的名称
16 | },
17 | // optimization: {
18 | // splitChunks: {
19 | // cacheGroups: {
20 | // styles: {
21 | // name: 'main',
22 | // test: /\.css$/,
23 | // chunks: 'all', // merge all the css chunk to one file
24 | // enforce: true
25 | // }
26 | // }
27 | // }
28 | // },
29 | plugins:[
30 | new ExtractTextPlugin({
31 | filename:'main.css',//重命名提取后的css文件
32 | allChunks: true //有了chunk,需要在此配置
33 | }),
34 | // new MiniCssExtractPlugin({
35 | // filename:'main.css',
36 | // }),
37 | new VueLoaderPlugin() //vue-loader,15的版本需要再添加plugin的配置
38 | ],
39 | module:{
40 | rules:[
41 | // {
42 | // test:/\.vue$/,
43 | // loader:'vue-loader',
44 | // options:{
45 | // loaders:{
46 | // css:[
47 | // 'vue-style-loader',
48 | // 'mini-css-extract-plugin',
49 | // 'css-loader'
50 | // ]
51 | // }
52 | // }
53 | // },
54 | // {
55 | // test: /\.css$/,
56 | // use:[ //数组形式的话,编译是从后往前。
57 | // MiniCssExtractPlugin.loader,
58 | // 'css-loader'
59 | // ]
60 | // },
61 | {
62 | test:/\.vue$/,
63 | loader:'vue-loader',
64 | options:{
65 | loaders:{
66 | css:ExtractTextPlugin.extract({
67 | use:'css-loader',
68 | fallback:'vue-style-loader'
69 | })
70 | }
71 | }
72 | },
73 | {
74 | test: /\.css$/,
75 | use: ExtractTextPlugin.extract({
76 | use: 'css-loader',
77 | fallback: 'style-loader'
78 | })
79 | },
80 | // 除非您要自定义 entry point(入口点) ,否则无需指定babel-loader。
81 | // {
82 | // test:/\.js$/,
83 | // loader:'babel-loader',
84 | // exclude:/node_modules/
85 | // },
86 | {
87 | test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
88 | loader:'url-loader?limit=1024' //文件小于1k就以base64形式加载
89 | }
90 | ]
91 | }
92 |
93 | };
94 | // module.exports = config
95 | //ES6: export default config
--------------------------------------------------------------------------------
/vue07/input_box/input-number.js:
--------------------------------------------------------------------------------
1 | function isValueNumber(value){
2 | return ( /(^-?[0-9]+\.{1}\d+$) | (^-?[1-9][0-9]*$) | (^-?0{1}$)/ ).test(value+'');
3 | }
4 |
5 | Vue.component('input-number',{
6 | template:'\
7 | \
8 | \
9 | \
10 |
',
11 | props:{ //因为是独立组件,所以应该对每个prop进行效验
12 | max:{
13 | type:Number,
14 | default:Infinity
15 | },
16 | min:{
17 | type:Number,
18 | default:-Infinity
19 | },
20 | value:{
21 | type:Number,
22 | default:0
23 | },
24 | step:{
25 | type:Number,
26 | default:1
27 | }
28 | },
29 | data:function(){
30 | // var val = this.value;
31 | // if( val > this.max ) val = this.max;
32 | // if( val < this.min ) val = this.min;
33 | // return{ currentValue : val }
34 | return {
35 | // Vue组件是单向数据流,无法从组件内部直接修改prop,value值。解决办法:给组件声明一个data。默认引用value的值。
36 | //使得可以从组件内部直接修改prop和value的值。就解决了引用父组件value的问题。
37 | currentValue:this.value
38 | }
39 | },
40 | watch:{ //用来监听某个prop或data的改变,改变时就会触发里边的函数
41 | currentValue:function(val){
42 | this.$emit('input',val); //在使用v-model时改变value的
43 | this.$emit('on-change',val); //触发自定义事件on-change告知父组件数字输入框的值有所改变,例子中没用到
44 | },
45 | value:function(val){
46 | this.updateValue(val)
47 | }
48 | },
49 | methods:{
50 | updateValue:function(val){ //过滤出一个正确的currentValue
51 | if( val > this.max ) val = this.max;
52 | if( val < this.min ) val = this.min;
53 | this.currentValue = val
54 | },
55 | handleDown:function(){
56 | if( this.currentValue <= this.min ) return;
57 | this.currentValue -= this.step
58 | },
59 | handleUp:function(){
60 | if( this.currentValue >= this.max ) return;
61 | this.currentValue += this.step
62 | },
63 | handleKeydown:function(event){
64 | if(event.keyCode==38){
65 | this.handleUp();
66 | }
67 | if(event.keyCode==40){
68 | this.handleDown() ;
69 | }
70 | },
71 | handleChange:function(event){ //handleChange绑在了上边的原生change事件上。判断当前输入的是否是数字。
72 | var val = event.target.value.trim();
73 |
74 | var max = this.max;
75 | var min = this.min;
76 |
77 | if( isValueNumber(val) ){
78 | val = Number(val);
79 | this.currentValue = val;
80 |
81 | if( val > max ){
82 | this.currentValue = max;
83 | }else if( val < min ){
84 | this.currentValue = min;
85 | }
86 | }else{
87 | event.target.value = this.currentValue;
88 | }
89 | }
90 | },
91 | mounted:function(){
92 | //在mounted钩子里调用updateValue()方法是因为第一次初始化时,也对value进行了过滤。
93 | // 还有种写法,在data选项里返回对象前进行过滤。参照data里的注释。
94 | this.updateValue(this.value)
95 | }
96 | })
--------------------------------------------------------------------------------
/vue14/shopping/src/views/product.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![]()
6 |
7 |
8 |
{{ product.name }}
9 |
¥ {{ product.cost }}
10 |
加入购物车
11 |
12 |
13 |
14 |
产品介绍
15 |
![]()
16 |
17 |
18 |
19 |
46 |
--------------------------------------------------------------------------------
/vue13/daily/src/style.css:
--------------------------------------------------------------------------------
1 | html, body{
2 | margin: 0;
3 | padding: 0;
4 | height: 100%;
5 | color: #657180;
6 | font-size: 16px;
7 | }
8 | .daily-menu{
9 | width: 150px;
10 | position: fixed;
11 | top: 0;
12 | bottom: 0;
13 | left: 0;
14 | overflow: auto;
15 | background: #f5f7f9;
16 | }
17 | .daily-menu-item{
18 | font-size: 18px;
19 | text-align: center;
20 | margin: 5px 0;
21 | padding: 10px 0;
22 | cursor: pointer;
23 | border-right: 2px solid transparent;
24 | transition: all .3s ease-in-out;
25 | }
26 | .daily-menu-item:hover{
27 | background: #e3e8ee;
28 | }
29 | .daily-menu-item.on{
30 | border-right: 2px solid #3399ff;
31 | }
32 |
33 | .daily-menu ul{
34 | list-style: none;
35 | }
36 | .daily-menu ul li a{
37 | display: block;
38 | color: inherit;
39 | text-decoration: none;
40 | padding: 5px 0;
41 | margin: 5px 0;
42 | cursor: pointer;
43 | }
44 | .daily-menu ul li a:hover, .daily-menu ul li a.on{
45 | color: #3399ff;
46 | }
47 |
48 | .daily-list{
49 | width: 300px;
50 | position: fixed;
51 | top: 0;
52 | bottom: 0;
53 | left: 150px;
54 | overflow: auto;
55 | border-right: 1px solid #d7dde4;
56 | }
57 | .daily-date{
58 | text-align: center;
59 | margin: 10px 0;
60 | }
61 | .daily-item{
62 | display: block;
63 | color: inherit;
64 | text-decoration: none;
65 | padding: 16px;
66 | overflow: hidden;
67 | cursor: pointer;
68 | transition: all .3s ease-in-out;
69 | }
70 | .daily-item:hover{
71 | background: #e3e8ee;
72 | }
73 | .daily-img{
74 | width: 80px;
75 | height: 80px;
76 | float: left;
77 | }
78 | .daily-img img{
79 | width: 100%;
80 | height: 100%;
81 | border-radius: 3px;
82 | }
83 | .daily-title{
84 | padding: 10px 5px 10px 90px;
85 | }
86 | .daily-title.noImg{
87 | padding-left: 5px;
88 | }
89 | .daily-article{
90 | margin-left: 450px;
91 | padding: 20px;
92 | }
93 | .daily-article-title{
94 | font-size: 28px;
95 | font-weight: bold;
96 | color: #222;
97 | padding: 10px 0;
98 | }
99 |
100 | .view-more a{
101 | display: block;
102 | cursor: pointer;
103 | background: #f5f7f9;
104 | text-align: center;
105 | color: inherit;
106 | text-decoration: none;
107 | padding: 4px 0;
108 | border-radius: 3px;
109 | }
110 |
111 | .daily-comments{
112 | margin: 10px 0;
113 | }
114 | .daily-comments span{
115 | display: block;
116 | margin: 10px 0;
117 | font-size: 20px;
118 | }
119 | .daily-comment{
120 | overflow: hidden;
121 | margin-bottom: 20px;
122 | padding-bottom: 20px;
123 | border-bottom: 1px dashed #e3e8ee;
124 | }
125 | .daily-comment-avatar{
126 | width: 50px;
127 | height: 50px;
128 | float: left;
129 | }
130 | .daily-comment-avatar img{
131 | width: 100%;
132 | height: 100%;
133 | border-radius: 3px;
134 | }
135 | .daily-comment-content{
136 | margin-left: 65px;
137 | }
138 | .daily-comment-name{
139 |
140 | }
141 | .daily-comment-time{
142 | color: #9ea7b4;
143 | font-size: 14px;
144 | margin-top: 5px;
145 | }
146 | .daily-comment-text{
147 | margin-top: 10px;
148 | }
--------------------------------------------------------------------------------
/vue09/vue9-13.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue9-13
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
118 |
119 |
--------------------------------------------------------------------------------
/vue14/shopping/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueRouter from 'vue-router';
3 | import Routers from './router';
4 | import Vuex from 'vuex';
5 | import App from './app.vue';
6 | import './style.css';
7 |
8 | import product_data from './product';
9 |
10 | Vue.use(VueRouter);
11 | Vue.use(Vuex);
12 |
13 | // 路由配置
14 | const RouterConfig = {
15 | // 使用 HTML5 的 History 路由模式
16 | mode: 'history',
17 | routes: Routers
18 | };
19 | const router = new VueRouter(RouterConfig);
20 |
21 | router.beforeEach((to, from, next) => {
22 | window.document.title = to.meta.title;
23 | next();
24 | });
25 |
26 | router.afterEach((to, from, next) => {
27 | window.scrollTo(0, 0);
28 | });
29 |
30 | // 数组排重
31 | function getFilterArray (array) {
32 | const res = [];
33 | const json = {};
34 | for (let i = 0; i < array.length; i++){
35 | const _self = array[i];
36 | if(!json[_self]){
37 | res.push(_self);
38 | json[_self] = 1;
39 | }
40 | }
41 | return res;
42 | }
43 |
44 | const store = new Vuex.Store({
45 | state: {
46 | productList: [],
47 | cartList: []
48 | },
49 | getters: {
50 | brands: state => {
51 | const brands = state.productList.map(item => item.brand);
52 | return getFilterArray(brands);
53 | },
54 | colors: state => {
55 | const colors = state.productList.map(item => item.color);
56 | return getFilterArray(colors);
57 | }
58 | },
59 | mutations: {
60 | // 添加商品列表
61 | setProductList (state, data) {
62 | state.productList = data;
63 | },
64 | // 添加到购物车
65 | addCart (state, id) {
66 | // 先判断购物车是否已有,如果有,数量+1
67 | const isAdded = state.cartList.find(item => item.id === id);
68 | if (isAdded) {
69 | isAdded.count ++;
70 | } else {
71 | state.cartList.push({
72 | id: id,
73 | count: 1
74 | })
75 | }
76 | },
77 | // 修改商品数量
78 | editCartCount (state, payload) {
79 | const product = state.cartList.find(item => item.id === payload.id);
80 | product.count += payload.count;
81 | },
82 | // 删除商品 findIndex返回数组中满足提供的测试函数的第一个元素的索引
83 | deleteCart (state, id) {
84 | const index = state.cartList.findIndex(item => item.id === id);
85 | state.cartList.splice(index, 1);
86 | },
87 | // 清空购物车
88 | emptyCart (state) {
89 | state.cartList = [];
90 | }
91 | },
92 | actions: {
93 | // 请求商品列表
94 | getProductList (context) {
95 | // 真实环境通过 ajax 获取,这里用异步模拟
96 | setTimeout(() => {
97 | context.commit('setProductList', product_data);
98 | }, 500);
99 | },
100 | // 购买
101 | buy (context) {
102 | // 真实环境应通过 ajax 提交购买请求后再清空购物列表
103 | return new Promise(resolve=> {
104 | setTimeout(() => {
105 | context.commit('emptyCart');
106 | resolve();
107 | }, 500)
108 | });
109 | }
110 | }
111 | });
112 |
113 | new Vue({
114 | el: '#app',
115 | router: router,
116 | store: store,
117 | render: h => {
118 | return h(App)
119 | }
120 | });
--------------------------------------------------------------------------------
/vue13/README13.md:
--------------------------------------------------------------------------------
1 | # 实战:知乎日报项目开发
2 |
3 | 日报项目以单页面呈现,基本覆盖了vue和webpack的核心功能,包括:
4 | + vue的单文件组件用法
5 | + vue的基本指令,自定义指令
6 | + 数据的获取,整理,可视化
7 | + prop,事件,子组件索引
8 | + es6模块
9 |
10 | *注意:写vue的时候a标签里不要再有href了,不然会出现意想不到的问题。*
11 |
12 | 跨域问题:
13 | 使用基于nodejs的request库来做代理
14 |
15 | `npm install request --save-dev`
16 |
17 | request 是一个用来简化 HTTP 请求操作的模块
18 | daily目录下新建proxy.js内容:
19 |
20 | ```
21 | const http = require('http');
22 | const request = require('request');
23 |
24 | const hostname = '192.168.10.122';
25 | const port = 8010;
26 | const imgPort = 8011;
27 |
28 | // 创建一个API 代理服务器
29 | const apiServer = http.createServer((req, res) => {
30 | const url = 'http://news-at.zhihu.com/api/4' + req.url;
31 | const options = {
32 | url: url
33 | };
34 |
35 | function callback (error, response, body) {
36 | if (!error && response.statusCode === 200) {
37 | // 设置编码类型,否则中文会显示为乱码
38 | res.setHeader('Content-Type', 'text/plain;charset=UTF-8');
39 | // 设置所有域允许跨域
40 | res.setHeader('Access-Control-Allow-Origin', '*');
41 | // 返回代理后的内容
42 | res.end(body);
43 | }
44 | }
45 | request.get(options, callback);
46 | });
47 |
48 | // 监听8010端口
49 | apiServer.listen(port, hostname, () => {
50 | console.log(`接口代理运行在 http://${hostname}:${port}/`);
51 | });
52 |
53 | // 创建一个图片代理服务
54 | const imgServer = http.createServer((req, res) => {
55 | const url = req.url.split('/img/')[1];
56 | const options = {
57 | url: url,
58 | encoding: null
59 | };
60 |
61 | function callback (error, response, body) {
62 | if (!error && response.statusCode === 200) {
63 | const contentType = response.headers['content-type'];
64 | res.setHeader('Content-Type', contentType);
65 | res.setHeader('Access-Control-Allow-Origin', '*');
66 | res.end(body);
67 | }
68 | }
69 | request.get(options, callback);
70 | });
71 |
72 | // 监听8011端口
73 | imgServer.listen(imgPort,hostname,()=>{
74 | console.log(`图片代理运行在http://${hostname}:${imgPort}/`);
75 | })
76 | ```
77 |
78 | Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
79 |
80 | `npm install axios --save`
81 |
82 | daily\src\libs下新建util.js内容:
83 |
84 | ```
85 | import axios from 'axios';
86 | // 基本配置
87 | const Util = {
88 | imgPath:'http://192.168.10.122:8011/img/';
89 | apiPath:'http://192.168.10.122:8010/'
90 | }
91 |
92 | // ajax通用配置
93 | Util.ajax = axios.create({ //自定义配置新建一个 axios 实例
94 | baseURL:Util.apiPath
95 | })
96 |
97 | // 添加响应拦截器 在响应被 then 或 catch 处理前拦截它们。
98 | Util.ajax.interceptors.response.use(res=>{
99 | return res.data;
100 | });
101 |
102 | export default Util;
103 | ```
104 | 比如在daily\src\app.vue中使用:
105 | ```
106 | import $ from './libs/util';
107 |
108 | methods:{
109 | getThemes(){
110 | //axios发起get请求
111 | $.ajax.get('themes').then(res =>{
112 | this.themes = res.others;
113 | })
114 | }
115 | }
116 | ```
117 |
118 | 使用concurrent 模块实现同时监听执行两条命令
119 |
120 | `npm install concurrently --save-dev`
121 |
122 | 然后在package.json里面的 "script" 里面的 "start"写入同时执行语句
123 |
124 | ```
125 | "scripts": {
126 | "dev": "webpack-dev-server --mode development --open --config webpack.config.js",
127 | "build": "webpack --progress --mode production --hide-modules --config webpack.prod.config.js",
128 | "start": "concurrently \"npm run dev\" \"node proxy.js\""
129 | },
130 | ```
131 |
132 |
133 |
--------------------------------------------------------------------------------
/vue13/daily/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
21 |
{{ formatDay(list.date) }}
22 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
121 |
--------------------------------------------------------------------------------
/vue09/sort_form/table.js:
--------------------------------------------------------------------------------
1 | Vue.component('vTable',{
2 | props:{
3 | columns:{ //描述每列的信息,并渲染在表头内
4 | type:Array,
5 | default:function(){
6 | return []
7 | }
8 | },
9 | data:{ //每一行的数据,由columns决定每一行里的各列排序。
10 | type:Array,
11 | default:function(){
12 | return []
13 | }
14 | }
15 | },
16 | // 为了排序后不影响原始数组,data里添加两个对应数据,组件操作在对应数据。不对原始数据做处理
17 | data:function(){
18 | return {
19 | currentColumns:[],
20 | currentData:[]
21 | }
22 | },
23 | // 用render构造虚拟DOM
24 | // 表格最外层元素,里面包含表头和表格主体。
25 | // thead是一行多列(一个tr多个th)。 tbody是多行多列(多个tr多个td)
26 | render:function(h){ //h就是createElement,只是换了个名称
27 | var _this = this;
28 | var ths = [];
29 | this.currentColumns.forEach(function(col,index){
30 | if( col.sortable ){
31 | ths.push(h('th',[
32 | h('span',col.title),
33 | // 升序
34 | h('a',{
35 | class:{
36 | on:col._sortType === 'asc'
37 | },
38 | on:{
39 | click:function(){
40 | _this.handleSortByAsc(index)
41 | }
42 | }
43 | },'↑'),
44 | // 降序
45 | h('a',{
46 | class:{
47 | on:col._sortType === 'desc'
48 | },
49 | on:{
50 | click:function(){
51 | _this.handleSortByDesc(index)
52 | }
53 | }
54 | },'↓')
55 | ]))
56 | }else{
57 | ths.push(h('th',col.title))
58 | }
59 | });
60 |
61 | var trs = [];
62 | // 先遍历所有行,然后在每一行内再遍历各列
63 | this.currentData.forEach(function(row){
64 | var tds = [];
65 | _this.currentColumns.forEach(function(cell){
66 | tds.push(h('td',row[cell.key]));
67 | });
68 | trs.push(h('tr',tds));
69 | });
70 |
71 | return h('table',[
72 | h('thead',[
73 | h('tr',ths)
74 | ]),
75 | h('tbody',trs)
76 | ])
77 | },
78 | methods:{
79 | // 把columns赋值给currentColumns
80 | makeColumns:function(){
81 | this.currentColumns = this.columns.map(function( col,index ){
82 | // 添加一个字段标识当前列排序的状态,赋值normal表示默认排序,就是不排序。
83 | col._sortType = 'normal';
84 | // 添加一个字段标识当前列在数组中的索引
85 | col._index = index;
86 | return col;
87 | })
88 | },
89 | // 把data赋值给currentData
90 | makeData:function(){
91 | this.currentData = this.data.map(function( row,index ){
92 | // 添加一个字段标识当前行在数组中的索引
93 | row._index = index;
94 | return row;
95 | })
96 | },
97 | // 升序操作 由小到大
98 | handleSortByAsc:function(index){
99 | var key = this.currentColumns[index].key;
100 | //排序前先将所有列的排序状态重置为normal
101 | this.currentColumns.forEach(function(col){
102 | col._sortType = 'normal';
103 | });
104 | // 设置当前列的排序状态为asc,对应到元素的class名称on
105 | this.currentColumns[index]._sortType = 'asc';
106 | this.currentData.sort(function(a,b){
107 | return a[key] > b[key] ? 1 : -1;
108 | // return a[key] - b[key]
109 | });
110 | },
111 | // 降序操作 由大到小
112 | handleSortByDesc:function(index){
113 | var key = this.currentColumns[index].key;
114 | this.currentColumns.forEach(function(col){
115 | col._sortType = 'normal';
116 | });
117 | this.currentColumns[index]._sortType = 'desc';
118 | this.currentData.sort(function(a,b){
119 | return a[key] < b[key] ? 1 : -1;
120 | // return b[key] - a[key]
121 | });
122 | }
123 | },
124 | //渲染完表格后,父级修改了data数据,比如增加,v-table的currentData也应该更新
125 | //如果某列已存在排序,应该直接处理一次排序。
126 | watch:{
127 | data:function(){
128 | this.makeData();
129 | var sortedColumn = this.currentColumns.filter(function(col){
130 | return col._sortType !== 'normal'; //返回排序的数组
131 | });
132 | if( sortedColumn.length ){ //如果有进行过排序
133 | if( sortedColumn[0]._sortType === 'asc' ){
134 | this.handleSortByAsc(sortedColumn[0]._index);
135 | }else{
136 | this.handleSortByDesc(sortedColumn[0]._index);
137 | }
138 | }
139 | }
140 | },
141 | mounted(){
142 | //v-table初始化时调用
143 | this.makeColumns();
144 | this.makeData();
145 | }
146 | })
--------------------------------------------------------------------------------