vue的学习心得体会

 

第一章vue的介绍... 3

1.1vue的介绍... 3

1.1.1 什么是vue. 3

1.1.2 MVVM的概念... 3

1.2创建vue实例... 4

1.2.1引入vue.js. 4

1.2.2创建一个vue实例... 4

1.3vue的生命周期函数... 5

1.4 vue指令... 8

1.4.1 属性绑定指令v-bind. 8

扫描二维码关注公众号,回复: 10389781 查看本文章

1.4.2事件绑定属性v-on. 8

1.4.3数据的双向绑定v-model 9

1.4.4  v-for和key属性... 9

1.4.5 v-if和v-show.. 11

1.5过滤器... 12

1.6组件... 13

1.6.1全局组件的注册... 13

1.6.2局部组件的注册... 14

1.6.3父组件向子组件传值... 15

1.6.4子组件向父组件传值... 17

1.7通过ref获取dom元素... 18

1.8路由... 19

1.8.1路由的基本使用... 19

1.8.2路由传参... 20

1.8.3路由的嵌套... 23

1.9 axios. 24

1.9.1get请求... 24

1.9.2post请求... 24

1.9.3拦截器... 25

第二章vue模块化开发项目... 25

2.1vue的脚手架搭建... 25

2.2基于element-ui开发... 27

2.2.1安装element-ui 27

2.2.2安装axios. 27

2.2.3vuex的使用... 28

2.2.4登录权限... 29

2.2.5封装子组件... 33

2.3项目的打包... 34

2.3.1静态资源路径不对... 34

2.3.2图片加载不进来... 35

 

 

 

 

 

1.1vue的介绍

1.1.1 什么是vue

Vue.js被定义为一个开发web界面的前端库,是一个非常轻量级的工具。本身具有响应式编程和组件化的特点。

在Vue中,一个核心的概念,就是让用户不再操作DOM元素,解放了用户的双手,让程序员可以更多的时间去关注业务逻辑。

官网:https://cn.vuejs.org/

1.1.2 MVVM的概念

MVVM是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端的视图层,分为了三部分 Model, View , ViewModel

1.2创建vue实例

1.2.1引入vue.js

要使用vue,首先要引入它的js库。

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

1.2.2创建一个vue实例

(1)首先我们需要在body里面id=”app”的div元素,这里是vue实例化后所控制的区域

(2)在<script></script>标签中实例化一个vue,其中el属性指向的是要操作的区域,data属性存放的是el要用到的数据。通过插值表达式{{msg}}很方便就能把数据渲染到页面上,不用手动去操作dom元素了。

<body>

    <div id="app">

       <p>{{ msg }}</p>

</div>

 

    <script>

    var vm = new Vue({

      el: '#app',       

      data: {

        msg: '欢迎学习Vue'

      }

    })

  </script>

</body>

1.3vue的生命周期函数

每个 Vue 实例在被创建时都要经过一系列的初始化过程。在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。当我们在程序中要默认加载一些数据时候,则可以考虑使用生命周期函数。

 

我们可以用代码来演示各个函数在什么阶段开始执行(注意:在vue中methods要使用data的数据,必须加上this)

<div id="app">

    <input type="button" value="修改msg" @click="msg='No'">

    <h3 id="h3">{{ msg }}</h3>

  </div>

  <script>

      var vm = new Vue({

      el: '#app',

      data: {

        msg: 'ok'

      },

      methods: {

        show() {

          console.log('执行了show方法')

        }

      },

      beforeCreate() {

           console.log("1:"+this.msg)

           this.show()

      },

      created() {

           console.log("2:"+this.msg)

           this.show()

      },

      beforeMount() {

           console.log("3:"+document.getElementById('h3').innerText)

      },

      mounted() {

           console.log("4:"+document.getElementById('h3').innerText)

      },

      beforeUpdate() {

        console.log('界面上元素的内容:' + document.getElementById('h3').innerText)

        console.log('data 中的 msg 数据是:' + this.msg)

      },

      updated() {

        console.log('界面上元素的内容:' + document.getElementById('h3').innerText)

        console.log('data 中的 msg 数据是:' + this.msg)

      }

    });

  </script>

 

 

 

我们可以打开控制台观察到:

于是我们可以得出:

  1. beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化;
  2. 在 created中,data 和 methods 都已经被初始化好了。
  3. 在 beforeMount 执行的时候,尚未把模板渲染到页面中,只是之前写的一些模板字符串。
  4. 当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的躺在我们的内存中,一动不动。

 

点击按钮进行修改msg的值,在控制台我们可以看到:

因此,我们可以得到:

当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时data数据是最新的,页面尚未和最新的数据保持同步。updated 事件执行的时候,页面和data 数据已经保持同步了,都是最新的。

1.4 vue指令

指令 (Directives) 是带有 v- 前缀的特殊特性。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

1.4.1 属性绑定指令v-bind

主要是用来绑定元素的一些基本属性,比如我想绑定input元素的title属性,那么我们就可以使用v-bind属性来实现。(它也可以缩写为  :),这样我们就可以在方法中动态修改这个title属性。

<input type="button" value="按钮" v-bind:title="mytitle ">

<input type="button" value="按钮"  :title="mytitle ">//两者是一样的

 

<script>

    var vm = new Vue({

      el: '#app',

      data: {

                mytitle: '这是一个自己定义的title'

      }

    })

  </script>

1.4.2事件绑定属性v-on

当我们想给元素添加触发的事件或者方法时,比如给button加上一个click事件,那么我们就需要使用v-on:click的指令,缩写(@click)

<input type="button" value="按钮" @click="show">

在vue中提供了methods属性,主要写一些方法,数据的操作逻辑。

var vm = new Vue({

      el: '#app',

      data: {

      },

      methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法

        show: function () {

          alert('Hello')

        }

      }

})

它等同于document.getElementById(id).onclick = function(){

      alert('Hello')}

1.4.3数据的双向绑定v-model

Vue的核心就是实现了数据的双向绑定,前面我们知道了v-bind可以实现数据的绑定,但它是单向的,而v-model可以实现data的数据和表单元素的双向绑定,在开发中我们肯定需要拿到页面上的值去和后端进行交互,这时候便可以很方便的使用v-model。注意: v-model 只能运用在表单元素中。

<div id="app">

    <h4>{{ msg }}</h4>

    <input  type="text" style="width:100%;" v-model="msg">

</div>

 

var vm = new Vue({

      el: '#app',

      data: {

        msg: '欢迎来到太平洋信用卡中心'

      },

      methods: {

      }

    });

当你在input中输入内容时,差值表达式{{msg}}即data的值也是同步变化的。

1.4.4  v-for和key属性

v-for的指令主要的作用是遍历。

1.循环普通的数组

比如现在有个list数组,我需要在页面上遍历展示出来:

(1)第一种方法:

<div id="app">

    <p>{{list[0]}}</p>

    <p>{{list[1]}}</p>

    <p>{{list[2]}}</p>

    <p>{{list[3]}}</p>

    <p>{{list[4]}}</p>

  </div>

 

  <script>

      var vm = new Vue({

        el: '#app',

        data: {

          list: [1, 2, 3, 4, 5, 6]

        }

     });

  </script>

(2)第二种使用v-for

<p v-for="(item, i) in list">索引值:{{i}} --- 每一项:{{item}}</p>

 

2.循环对象数组

<div id="app">

    <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p>

  </div>

 

  <script>

    var vm = new Vue({

      el: '#app',

      data: {

        list: [

          { id: 1, name: 'zs1' },

          { id: 2, name: 'zs2' },

          { id: 3, name: 'zs3' },

          { id: 4, name: 'zs4' }

        ]

      },

      methods: {}

    });

  </script>

 

3.循环对象

在遍历对象身上的键值对的时候,除了有val ,key在第三个位置还有一个索引。

<div id="app">

     <p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>

</div>

 

  <script>

      var vm = new Vue({

      el: '#app',

      data: {

        user: {

          id: 1,

          name: '小明',

          gender: '男'

        }

      },

      methods: {}

    });

  </script>

 

4.key属性的使用

(1)v-for 循环的时候,key 属性只能使用 number获取string

(2) key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值

(3)在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值

<div id="app">

    <div>

      <label>Id:

        <input type="text" v-model="id">

      </label>

      <label>Name:

        <input type="text" v-model="name">

      </label>

      <input type="button" value="添加" @click="add">

    </div>

    <p v-for="item in list" :key="item.id">

      <input type="checkbox">{{item.id}} --- {{item.name}}

    </p>

  </div>

  <script>

      var vm = new Vue({

      el: '#app',

      data: {

        id: '',

        name: '',

        list: [

          { id: 1, name: '小交' },

          { id: 2, name: '小通' },

          { id: 3, name: '小银' },

          { id: 4, name: '小行' }

        ]

      },

      methods: {

        add() {

          this.list.unshift({ id: this.id, name: this.name })

        }

      }

    });

 

1.4.5 v-if和v-show

v-if和v-show可以实现元素的显示和隐藏。

<div id="app">

    <input type="button" value="toggle" @click="flag=!flag">

    <h3 v-if="flag">这是用v-if控制的元素</h3>

    <h3 v-show="flag">这是用v-show控制的元素</h3>

  </div>

  <script>

      var vm = new Vue({

        el: '#app',

        data: {

          flag: false

        }

      });

  </script>

两者的区别是:

(1)v-if 的特点:每次都会重新删除或创建元素

     v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式

(2)v-if 有较高的切换性能消耗

     v-show 有较高的初始渲染消耗

(3)如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show

如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if

1.5过滤器

开发中我们有时候需要固定的参数格式,比如时间、邮箱等,一方面你可以使用验证函数,另一方面你可以使用vue提供的过滤器。Vue.js允许在表达式后添加过滤器,用管道符“|”表示。过滤器的本质是一个函数,接受管道符前面作为初始值,同时也能接受额外的参数,返回的值为经过处理后的输出值。多个过滤器可以进行串联。

<div id="app">

         <p>{{msg}}</p>

         <p>{{msg | msgFormat}}</p>

         <p>{{msg | replaseMsg('招商')}}</p>

         <p>{{msg | replaseMsg('招商') | msgFormat}}</p>

</div>

<script>

         var vm = new Vue({

           el: '#app',

           data: {

                   msg: '交通银行信用卡中心'

           },

           methods: {},

           filters:{

                   msgFormat(value){

                      return value+"欢迎您!"

                   },

                   replaseMsg(value,arg1){

                      return value.replace('交通',arg1)

                   }

           }

         });

</script>

 

1.6组件

为了解决代码复用问题,vue也有一套自己的组件系统,通过自定义的标签以及对原生HTML元素的拓展实现组件化。

1.6.1全局组件的注册

全局组件可以在可以在整个项目的任何地方使用。比如后面要说到的axios,route等。

(1)使用Vue.extend 来创建全局的Vue组件

var com1 = Vue.extend({

       template: '<h3>这是使用 Vue.extend 创建的组件</h3>'

})

通过 template 属性,指定了组件要展示的HTML结构,但此时只是通过组件构造器创建了一个组件,还需要将组件注册到应用中。

(2)使用 Vue.component('组件的名称', 创建出来的组件模板对象)

Vue.component('mycom1', com1)

如果使用 Vue.component 定义全局组件的时候,组件名称使用了驼峰命名,则在引用组件的时候,需要把 大写的驼峰改为小写的字母,同时,两个单词之前,使用 - 链接;如果不使用驼峰,则直接拿名称来使用即可;

当然上述代码可以简化成:

Vue.component('mycom1', Vue.extend({

      template: '<h3>这是使用 Vue.extend 创建的组件</h3>'

}))

再进一步我们也可以写成:

Vue.component('mycom1', {

      template: '<h3>这是使用 Vue.extend 创建的组件</h3>'

})

整个使用方法代码如下:

<div id="app">

<mycom1></mycom1>

</div>

<script>

var com1 = Vue.extend({

   template: '<h3>这是使用 Vue.extend 创建的组件</h3>'

})

Vue.component('mycom1', com1)

var vm = new Vue({

    el: '#app',

    data: {},

    methods: {}

});

</script>

(3)使用这是通过 template 元素,在div控制的外部定义的组件结构

<div id="app">

    <mycom3></mycom3>

</div>

<template id="tmpl">

    <div>

      <h1>这是通过 template 元素,在外部定义的组件结构</h1>

    </div>

</template>

<script>

    Vue.component('mycom3', {

      template: '#tmpl'

    })

    var vm = new Vue({

      el: '#app',

      data: {},

      methods: {}

    });

</script>

 

1.6.2局部组件的注册

局部组件只能在被注册的组件中使用,而无法在其他组件中使用。而全局注册的组件可以在任何地方使用。

<div id="app">

    <mycom3></mycom3>

    <login></login>

  </div>

  <div id="app2">

    <mycom3></mycom3>

    <login></login>

  </div>

  <template id="tmp1">

    <div>

      <h1>这是通过 template 元素,在外部定义的组件结构</h1>

    </div>

  </template>

  <template id="tmpl2">

    <h1>这是私有的 login组件</h1>

  </template>

 

  <script>

    Vue.component('mycom3', {

      template: '#tmp1'

    })

    var vm = new Vue({

      el: '#app',

      data: {},

      methods: {}

    });

    var vm2 = new Vue({

      el: '#app2',

      data: {},

      methods: {},

      filters: {},

      directives: {},

      components: { // 定义实例内部私有组件的

        login: {

          template: '#tmpl2'

        }

      },

    })

  </script>

此时我们可以看到控制台报一个错

注意:

1. 组件可以有自己的 data 数据

2. 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象,但是组件中的 data 必须是一个方法

3. 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行;

4. 组件中 的data 数据,使用方式,和实例中的 data 使用方式完全一样

 

1.6.3父组件向子组件传值

首先我们看一张图:

组件的作用域是孤立的,也就是说子组件是无法直接调用父组件的数据的,因此需要通过props将父组件的数据传递给子组件。

父组件,可以在引用子组件的时候,通过属性绑定(v-bind:)的形式, 把需要传递给子组件的数据,以属性绑定的形式,传递到子组件内部,供子组件使用;而子组件先在 props 数组中,定义一下,这样才能使用这个数据。

<div id="app">

    <com1 v-bind:parentmsg="msg"></com1>

</div>

 

<script>

    var vm = new Vue({

      el: '#app',

      data: {

        msg: '父组件中的数据'

      },

      methods: {},

      components: {

        com1: {

            data() {

                     return {

                     }

            },

                 template: '<h1 >这是子组件 --- {{ parentmsg }}</h1>',

                 props: ['parentmsg'],

                 components: {}

        }

      }

    });

</script>

 

1.6.4子组件向父组件传值

项目开发中肯定也有子组件向父组件传值的情况,比如:

如果我们想子组件调用父组件的方法,那么就需要事件绑定机制v-on,子组件就能够通过某些方式,来调用传递进去的这个方法了。即使用$emit()方法。这个方法可以传两个参数,第一个固定是父组件绑定的事件名,而第二个是自定义的,因此我们可以把子组件的的数据放到第二个参数上,实现子组件向父组件传值。

<div id="app">

       <com2 @func="show"></com2>

</div>

  <template id="tmpl">

    <div>

      <h1>这是子组件</h1>

      <input type="button" value="触发父组件传递过来的 func 方法" @click="myclick">

    </div>

  </template>

  <script>

    var com2 = {

      template: '#tmpl',

      data() {

        return {

          sonmsg: { name: '小头儿子', age: 6 }

        }

      },

      methods: {

        myclick() {

           this.$emit('func', this.sonmsg)

        }

      }

    }

    // 创建 Vue 实例,得到 ViewModel

    var vm = new Vue({

      el: '#app',

      data: {

        datamsgFormSon: null

      },

      methods: {

        show(data) {

          console.log(data);

          this.datamsgFormSon = data

        }

      },

 

      components: {

         com2: com2

      }

    });

  </script>

控制台显示:

 

1.7通过ref获取dom元素

当你想动态去操作dom元素时,比如动态添加css样式,此时肯定要获取这个dom元素。

在vue中如果想获取dom元素,那么可以通过ref属性来获取。

<div id="app">

    <input type="button" value="获取元素" @click="getElement" ref="mybtn">

    <h3 id="myh3" ref="myh3">哈哈哈, 今天天气太好了!!!</h3>

  </div>

  <script>

    var vm = new Vue({

      el: '#app',

      data: {},

      methods: {

        getElement() {

          console.log("原生获取:"+document.getElementById('myh3').innerText)

          console.log("ref获取:"+this.$refs.myh3.innerText)

        }

      }

    });

 

1.8路由

vue常用于开发单页面应用,要想实现页面间的跳转和切换就要用到路由了。

推荐网址:http://www.cnblogs.com/avon/p/5943008.html

官方文档: https://router.vuejs.org/zh-cn/essentials/getting-started.html

1.8.1路由的基本使用

1. 导入 vue-router 组件类库;

2. 使用 router-link 组件来导航;

<router-link to="/login">登录</router-link>

<router-link to="/register">注册</router-link>

3. 使用 router-view 组件来显示匹配到的组件。

具体代码如下:

<div id="app">

             <router-link to="/login" >登录</router-link>

             <router-link to="/register">注册</router-link>

             <router-view></router-view>

           </div>

 

  <script>

    // 组件的模板对象

    var login = {

      template: '<h1>登录组件</h1>'

    }

 

    var register = {

      template: '<h1>注册组件</h1>'

    }

    var routerObj = new VueRouter({

      routes: [

        { path: '/', redirect: '/login' },

        { path: '/login', component: login },

        { path: '/register', component: register }

      ],

    })

    var vm = new Vue({

      el: '#app',

      data: {},

      methods: {},

      router: routerObj

    });

  </script>

routes路由匹配规则,每一条路由规则都是一个对象,它必须包含两个属性path和component。

1.8.2路由传参

之前我们说了父子组件的传值,当然有时候两个组件并不是父子关系,但是需要传递一些简单的参数时,比如我登录成功,我需要在某一个组件中使用账号信息,这时候可以用路由传参的方式快速解决问题。

1.通过$route.query

<div id="app">

    <router-link to="/login?id=10&name=zs">登录</router-link>

    <router-link to="/register">注册</router-link>

    <router-view></router-view>

</div>

<script>

    var login = {

      template: '<h1>登录 --- {{ $route.query.id }} --- {{ $route.query.name }}</h1>',

      data(){

        return {

        }

      },

      created(){ // 组件的生命周期钩子函数

        console.log(this.$route)

        console.log(this.$route.query.id)

      }

    }

    var register = {

      template: '<h1>注册</h1>'

    }

    var router = new VueRouter({

      routes: [

        { path: '/login', component: login },

        { path: '/register', component: register }

      ]

    })

      var vm = new Vue({

      el: '#app',

      data: {},

      methods: {},

      router

    });

</script>

可以看到控制台的打印信息如下:

我们可以看到route是一个json对象,而里面有query这个对象属性,而这个对象里面的参数就是我们需要传的值。同时我们还注意到里面有一个params这个对象,由此我们得到第二种路由传参的方式。

 

2.通过 $route.params

<div id="app">

    <router-link to="/login/12/ls">登录</router-link>

    <router-link to="/register">注册</router-link>

    <router-view></router-view>

  </div>

  <script>

    var login = {

      template: '<h1>登录 --- {{ $route.params.id }} --- {{ $route.params.name }}</h1>',

      data(){

        return {

            }

      },

      created(){

        console.log(this.$route.params.id)

      }

    }

    var register = {

      template: '<h1>注册</h1>'

    }

    var router = new VueRouter({

      routes: [

        { path: '/login/:id/:name', component: login },

        { path: '/register', component: register }

      ]

    })

      var vm = new Vue({

      el: '#app',

      data: {},

      methods: {},

      // router: router

      router

    });

  </script>

注意,使用这种方式传参是需要在path中绑定参数的。

控制台也是可以拿到值。

1.8.3路由的嵌套

一般实际开发中,往往是有多级菜单的,此时就需要使用children来实现路由嵌套。具体用法如下:

<div id="app">

    <router-link to="/account">Account</router-link>

    <router-view></router-view>

</div>

  <template id="tmpl">

    <div>

      <h1>这是 Account 组件</h1>

      <router-link to="/account/login">登录</router-link>

      <router-link to="/account/register">注册</router-link>

      <router-view></router-view>

    </div>

  </template>

  <script>

      var account = {

      template: '#tmpl'

    }

    var login = {

      template: '<h3>登录</h3>'

    }

    var register = {

      template: '<h3>注册</h3>'

    }

 

    var router = new VueRouter({

      routes: [

        {

          path: '/account',

          component: account,

          children: [

            { path: 'login', component: login },

            { path: 'register', component: register }

          ]

        }

      ]

    })

      var vm = new Vue({

      el: '#app',

      data: {},

      methods: {},

      router

    });

  </script>

注意:使用 children 属性,实现子路由,同时,子路由的 path 前面,不要带 / ,否则永远以根路径开始请求,这样不方便我们用户去理解URL地址

1.9 axios

实际开发中免不了要和后端用异步进行交互,第一时间你可能会想到jquery的ajax,vue也可以集成jQuery,但是仅仅为了使用ajax就引入jQuery,会增加浏览器的响应速度,兼容性也不好。而vue2.0中有自己的一套方法axios。

推荐一个中文的api网址https://www.cnblogs.com/libin-1/p/6607945.html

首先要使用这个插件,需要引入这个包。

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

1.9.1get请求

执行get请求的语法格式如下:

// 向具有指定ID的用户发出请求

axios.get('/user?ID=12345')

.then(function (response) {

console.log(response);

})

.catch(function (error) {

console.log(error);

});

 

// 也可以通过 params 对象传递参数

axios.get('/user', {

params: {

ID: 12345

}

})

.then(function (response) {

console.log(response);

})

.catch(function (error) {

console.log(error);

});

 

1.9.2post请求

Post请求的语法格式如下:

axios.post('/user', {

firstName: 'Fred',

lastName: 'Flintstone'

})

.then(function (response) {

console.log(response);

})

.catch(function (error) {

console.log(error);

});

1.9.3拦截器

 

为了保证系统的安全性,一般后台都会进行token验证,所以前台发送的请求中需要把这个token带着,因此可以使用拦截器来实现。

//添加请求拦截器

axios.interceptors.request.usefunctionconfig{

     //在发送请求之前做某事

     return config;

   }functionerror{

     //请求错误时做些事

     return Promise.rejecterror;

   };

 

//添加响应拦截器

axios.interceptors.response.usefunctionresponse{

     //对响应数据做些事

     return response;

   }functionerror{

     //请求错误时做些事

     return Promise.rejecterror;

   };

 

 

第二章vue模块化开发项目

为了更好的用模块化的思想去开发项目,vue官方推荐用脚手架去进行开发。

2.1vue的脚手架搭建

Vue官方提供一个搭建脚手架的工具CLI。我们通过npm去安装vue,npm能和webpack等模块打包器配合使用。首先确保你安装了node.js。接下来开始搭建vue工程。

  1. (windows+R)npm install --global vue-cli  这里推荐用cnpm去安装,国内的淘宝镜像,下载包速度更快。

安装cnpm。(npm install -g cnpm --registry=https://registry.npm.taobao.org)

  1. vue init webpack my-project

它生成的目录结构是这样的。

 

   build:存放webpack相关配置和脚本。

   config:存放配置文件,用于区分开发环境、测试环境、线上环境。

   src:项目源码及需要引用的资源文件。

static:不需要webpack处理的静态资源。

test:用于存放测试文件。

package.json:需要下载的依赖包。

 

  1. cd 这个文件夹,执行cnpm install;
  2. cnpm run dev。

一个简单的vue工程就搭建好了

 

2.2基于element-ui开发

为了更好更快的开发项目,有很多完美集成vue的前端ui库,这里推荐使用饿了么团队开发的适用于pc端的element-ui。

官网:http://element-cn.eleme.io/#/zh-CN

2.2.1安装element-ui

1.cnpm i element-ui –S

2.全局引入element-ui

main.js中加入:

import ElementUI from 'element-ui';

import 'element-ui/lib/theme-chalk/index.css';

 

Vue.use(ElementUI);

或者我们也可以按需引入

import { Button } from 'element-ui';

Vue.component(Button.name, Button);

 

2.2.2安装axios

1.cnpm install axios –S

2.在main.js中

import axios from 'axios';

import qs from 'qs';//这是将字符串转成json字符串

 

2.2.3vuex的使用

在项目中我们有时候会遇到两个组件不是子父组件的关系,这个时候我们传值就比较繁琐。

1. 运行 cnpm i vuex –S

2.可以在src下建一个store文件夹,在该文件夹下新建一个index.js

import Vue from 'vue'

import vuex from 'vuex'

Vue.use(vuex);

export default new vuex.Store({

state:{

// 大家可以把 state 想象成 组件中的 data ,专门用来存储数据的

// 如果在 组件中,想要访问,store 中的数据,只能通过 this.$store.state.*** 来访问

    },

    mutations:{

        //如果要操作 store 中的 state 值,只能通过 调用 mutations 提供的方法,才能操作对应的数据,不推荐直接操作 state 中的数据,因为 万一导致了数据的紊乱,不能快速定位到错误的原因,因为,每个组件都可能有操作数据的方法;

    }

    getters:{

             //向外提供state里的数据

    }

})

a. state中的数据,不能直接修改,如果想要修改,必须通过 mutations

 b. 如果组件想要直接 从 state 上获取数据: 需要 this.$store.state.***

c. 如果 组件,想要修改数据,必须使用 mutations 提供的方法,需要通过 this.$store.commit('方法的名称', 唯一的一个参数)

 d. 如果 store 中 state 上的数据, 在对外提供的时候,需要做一层包装,那么 ,推荐使用 getters, 如果需要使用 getters ,则用 this.$store.getters.***

 

3.在main.js中

import store from './store'//使用vuex

new Vue({

  el: '#app',

  router,

  store,

  components: { App },

  template: '<App/>'

})

 

2.2.4登录权限

做后台项目,权限验证也是很重要的一个环节。我们需要根据不同的权限去动态生成路由。比如我们项目中有三个角色:员工、经理、管理员。

  1. 在route.js中,我们把不同权限的路由分别区分出来。核心代码如下:

//所有权限通用路由表

//如首页和登录页和一些不用权限的公用页面

export const constantRouterMap = [

  //登录

  {path: '/',component: Login},

  {path:'/register',component:register},

  {path: '/main',component: Main,name:'main',

    children:[//子路由

             /*{path:'/home',component:Home},

      {path:'/',component:Home},*/

      {path:'/changePassword',component:ChangePassword},//修改密码

    ]

  },

 

]

 

//异步挂载的路由

//动态需要根据权限加载的路由表

//manager:开发经理及以上    work员工   admin 管理员

export const asyncMagRouterMap = [

         {path: '/main',component: Main,name:'main',

                   children:[//子路由

                     {path:'/home',component:Home},

      {path:'*',component:Home},

      {path:'/logReport',component:LogReport,name:'LogReport'},// 这里设置,当前路由需要校验

      //{path:'/logReport/:dateTime',component:LogReport,name:'LogReport'},// 这里设置,当前路由需要校验

      {path: '/LaunchConference',component: LaunchConference},

      {path: '/ConferencePreparation',component: ConferencePreparation},

      {path: '/myMeetingReport',component: myMeetingReport},

      {path: '/queryMeeting',component: QueryMeeting},

      {path:'/reviewmeeting',component:reviewmeeting},

      {path: '/StaffMeetingQuery',component: StaffMeetingQuery},//员工会议查询

      {path:'/postManagement',component:postManagement},//会后管理

           ]

  },

  { path: '/404', component:ErrorPage},

  { path: '*', redirect: '/404', hidden: true }

];

//员工

export const asyncWorkRouterMap = [

         {path: '/main',component: Main,name:'main',

                   children:[//子路由

                     {path:'/home',component:Home},

      {path:'*',component:Home},

      {path:'/logReport',component:LogReport,name:'LogReport'},// 这里设置,当前路由需要校验

      {path: '/LaunchConference',component: LaunchConference},

      {path: '/ConferencePreparation',component: ConferencePreparation},

      {path: '/myMeetingReport',component: myMeetingReport},

      {path: '/queryMeeting',component: QueryMeeting},

      {path:'/postManagement',component:postManagement},//会后管理

           ]

  },

  { path: '/404', component:ErrorPage},

  { path: '*', redirect: '/404', hidden: true }

];

//管理员

export const asyncAdminRouterMap = [

         {path: '/main',component: Main,name:'main',

                   children:[//子路由

                            {path:'*',component:CalendarManager},

      {path:'/calendarManager', component: CalendarManager},//管理日历

             {path:'/configWorkItem',component:workItemManager},

             {path:'/configSysProject',component:sysProjectManager},

             {path:'/configMapping',component:workItemMappingSysProjectManager}

           ]

  },

  { path: '/404', component:ErrorPage},

  { path: '*', redirect: '/404', hidden: true }

];

export default new Router({

    routes: constantRouterMap

})

注意事项:这里有一个需要非常注意的地方就是 404 页面一定要最后加载,如果放在constantRouterMap一同声明了404,后面的所以页面都会被拦截到404

 

  1. mian.js中,首先我们需要用到route的钩子函数(生命周期函数)router.beforeEach(to,from,next)
  1. to:router即将进入的路由对象
  2. from:当前导航即将离开的路由
  3. next:Function,进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。

 

router.beforeEach((to,from,next)=>{

         console.log(to,from,next)

         var userInfo = JSON.parse(window.sessionStorage.getItem('session')) ;//获取浏览器缓存的用户信息

         //console.log(userInfo.roleName)

         //var userInfo = store.stste.token

         if(userInfo){ //如果有就直接到首页咯

                   //if(userInfo.roleName)

                  var roleName = userInfo.roleName

                   switch (roleName){

                            case '管理员':

                                     store.dispatch('GenerateRoutes','admin').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })

                                     /*store.dispatch('AdminRoutes').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })*/

                                     store.commit("setIsMag",false)

                                     store.commit("setIsShow",false)

                                     store.commit("setIsAdmin",true)

                                     break;

                            case '工程师':

                                     store.dispatch('GenerateRoutes','work').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })

                                     /*store.dispatch('WorkRoutes').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })*/

                                     store.commit("setIsAdmin",false)

                                     store.commit("setIsShow",false)

                                     store.commit("setIsMag",true)

                                     break;

                            default:

                                     store.dispatch('GenerateRoutes','manager').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })

                                     /*store.dispatch('MagRoutes').then(() => {

                                     router.addRoutes(store.state.addRouters) // 动态添加可访问路由表

                                     })*/

                                     store.commit("setIsAdmin",false)

                           store.commit("setIsMag",true)

                           store.commit("setIsShow",true)

                                     break;

                   }

                   next();

                   //next();

    }

    else {

        if(to.path=='/' || to.path=='/register'){ //如果是登录页面路径,就直接next()

            next();

        } else { //不然就跳转到登录;

            next('/');

        }

    }

}),

 

  1. store.js中

import Vue from 'vue'

import vuex from 'vuex'

import {constantRouterMap,asyncMagRouterMap,asyncWorkRouterMap,asyncAdminRouterMap } from '../router';

Vue.use(vuex);

export default new vuex.Store({

    state:{

        routers: constantRouterMap,

             addRouters: []

    },

    mutations:{

        SET_ROUTERS(state, routers){//设置动态  静态路由转换的

                       state.addRouters = routers;

                       state.routers = constantRouterMap.concat(routers);

             }

    },

    actions:{

             GenerateRoutes({ commit },data) {

                       switch (data){

                                case "admin":

                                    commit('SET_ROUTERS', asyncAdminRouterMap);        

                                         break;

                                     case "work":

                                         commit('SET_ROUTERS', asyncWorkRouterMap); 

                                               break;

                                default:

                                         commit('SET_ROUTERS', asyncMagRouterMap);  

                                         break;

                       }

             }

    }

})

 

 

2.2.5封装子组件

子组件中一般不能有异步请求,子组件的数据都是通过父组件传来的。

下面通过在countUp.js封装一个计时器组件。

  1. 安装countUp.js

cnpm install countup.js

  1. 新建一个VueCountUp.vue文件
  1. <template>
  2.   <span ref='countup'></span>
  3. </template>
  4.  
  5. <script>
  6. import CountUp from 'countup.js'
  7. export default {
  8.   data () {
  9.     return {
  10.       numAnim:null
  11.     }
  12.   },
  13.    props: {
  14.             start: {
  15.                 type: Number,
  16.                 default: 0
  17.             },
  18.             end: {
  19.                 type: Number,
  20.                 default: 2018
  21.             },
  22.             decimal: {
  23.                 type: Number,
  24.                 default: 0
  25.             },
  26.             duration: {
  27.                 type: Number,
  28.                 default: 2.5
  29.             },
  30.             options: {
  31.                 type: Object
  32.             }
  33.         },
  34.   mounted(){
  35.     this.initCountUp()
  36.   },
  37.   methods:{
  38.     initCountUp(){
  39.       this.numAnim = new CountUp(this.$refs.countup, this.start,
  40.                         this.end,
  41.                         this.decimal,
  42.                         this.duration,
  43.                         this.options
  44.                 );
  45.       this.numAnim.start();
  46.     }
  47.   }
  48. }
  49. </script>

 

 

  1. 在App.vue中使用该组件
  1. <template>
  2.   <div id="app">
  3.     <vue-count-up :end="5000" :duration="2.5"></vue-count-up>
  4.   </div>
  5. </template>
  6.  
  7. <script>
  8. import VueCountUp from '@/components/VueCountUp.vue'
  9. export default {
  10. components:{
  11.             VueCountUp
  12.   }
  13. }
  14. </script>

 

2.3项目的打包

当vue项目完成后我们需要将它打包出来放到服务器下即可运行。

执行cnpm run build 命令,可以看到打包后生成的文件夹。

2.3.1静态资源路径不对

1在打包的时候可能会出现的问题。

控制台如下:

 

 

解决方法:找到config目录下的index.js,在如下图所示的地方加上一个点即可。

 

2.3.2图片加载不进来

这是因为在模块加载器的url加载器limt限制大小的关系。将build文件夹下更改一下限制。

发布了11 篇原创文章 · 获赞 6 · 访问量 5728

猜你喜欢

转载自blog.csdn.net/Ruipower/article/details/85095015