Vue 学习

一、Vue 简介

Vue 是基于ES6规范并结合了AngulaJS的模块化开发和React的虚拟DOM,虚拟DOM就是把DOM操作放到内存中执行

什么是MVVM

MVVM

他区别与MVC模式,MVC模式大致流程是view发送请求,通过controller,操作Model数据之后,结果通过controller返回View,view处理结果,展示给用户

而MVVM模式则是,view其实只做显示用,实际请求由ViewModel发出,Model处理完数据之后,ViewModel接收到数据,因为ViewModel和View是双向绑定的

所以数据会直接展示在View层。

二、Vue入门

总结

1. 简单环境搭建

  1. 以idea,为例,通过file–settings-plugins,安装vue.js

  1. 将idea环境调成ES6,以为vue是基于es6规范写的,防止写代码时报错

2. 条件和循环

注意需要引入<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id = "app">
    {{word}}
     <li v-for="item in items">
        {{item.message}}
     </li>
</div>
<div id = "app2">
    <h1 v-if="word==='A'">A</h1>
    <h1 v-else-if="word==='B'">B</h1>
    <h1 v-else-if="word==='D'">D</h1>
    <h1 v-else>C</h1>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    var vm = new Vue({
        el: '#app2',
        data :{
            word : 'A'
        }
    });

    var vm = new Vue({
        el: '#app',
        data :{
            word : 'B',
            items: [
                {message: 'Hello Vue!', message:'2'},
                {message: 'Hello Vue2!'}
            ]
        }
    });


</script>
</html>

3.绑定事件v-on

v-on 用于绑定事件,可以使用@符号代替

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<div id="app">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">两级反转</button>
</div>

<div id="app2">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage2('嗨森')">两级反转</button>
</div>


</body>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            message: '不嗨森'
        },
        methods:{
            reverseMessage:function () {
                alert(this.message.split(''));
                alert(this.message.split('').reverse());
                //split将字符串变成字符数组
                //reverse将字符数组反转,变成新数组
                //join,将字符数组变成字符串
                this.message = this.message.split('').reverse().join('')
            }
        }
    });

    var vm = new Vue({
        el: '#app2',
        data: {
            message: '不嗨森'
        },
        methods:{
            reverseMessage2:function (message) {
                this.message = message;
            }
        }
    });

</script>
</html>

4.数据双向绑定v-model

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app-6">
    <p>{{ message }}</p>
    <input v-model="message">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    var app6 = new Vue({
        el: '#app-6',
        data: {
            message: 'Hello Vue!'
        }
    })
</script>

</html>

5.给组件绑定参数v-bind

将参数传给绑定的组件中,组件中使用props接收,可以使用:符号代替

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <myli v-for="item in items" v-bind:temp="item"></myli>
<!--    <myli v-bind:test="message"></myli>-->
</div>

</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    Vue.component("myli", {
        props:['temp', 'test'],
        template:'<li>{{temp}}</li>'
    });

    var vm = new Vue({
        el: '#app',
        data: {
            items: ['Java','Vue','Linux']
        }
    })

</script>

</html>

6.组合组件slot插槽

组件内部事件绑定事件需要使用 this.$emit(‘事件名’, 参数)调用

以下为双击删除,指定的<li>,由于<li>是组件化的,所以删除它, 需要删除它绑定的数据,即items中的值,但是组件并不能直接访问到Vue中的数据

所以需要通过view层绑定一个自定义事件customremove,然后组件中通过this.$emit(‘customremove’, 参数)去调用,从而实现删除标签的功能。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">

    <todo>
        <todo-title slot="todo-title" :title="title"></todo-title>
        <todo-items slot="todo-items" v-for="(item,index) in items"
                    :item="item" :index="index" @customremove="removeItem(index)"></todo-items>
    </todo>

</div>

</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    Vue.component("todo", {
        template: '<div>\
                    <slot name="todo-title"></slot>\
                    <ul>\
                        <slot name = "todo-items"></slot>\
                    </ul>\
                 </div>'
    });

    Vue.component("todo-title",{
        props: ['title'],
        template: '<div>{{title}}</div>'
    });

    Vue.component("todo-items",{
        props:['item','index'],
        template: '<li>{{item}}---<button @dblclick="remove(index)">删除</button></li>',
        methods:{
            remove: function (index) {
                this.$emit('customremove', index)
            }
        }
    });

    var vm = new Vue({
        el: '#app',
        data: {
            title:'课程',
            items: ['Java','Vue','Linux']
        },
        a:{

        },
        methods:{
            removeItem:function (index) {
                //删除当前下标元素,splice操作数组的万能方法
                this.items.splice(index, 1);
            }
        }


    })


</script>

</html>

7.计算机属性

计算机属性是Vue的特色,可以理解成缓存,可以理解成,计算过1+1等于2后,下一次在遇到1+1就直接使用缓存中的数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <p>currentTime1 {{currentTime1()}}</p>
    <p>currentTime2 {{currentTime2}}</p>
</div>

</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message:'123'
        },
        methods:{
            currentTime1:function () {
                return Date.now()
            }
        },
        computed:{
            //currentTime2的结果被缓存在内存中,如果其中的值被改变,值才会别刷新,
            // 如message改变,currentTime2返回的值就会别改变
            currentTime2:function () {
                this.message;
                return Date.now()
            }
        }

    })

</script>

</html>

8.axios简单使用

注意需要引入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<!--    解决屏闪问题 -->
<style>

    [v-cloak] {
        display: none !important;
    }
</style>
<body>

<div id="app" v-cloak>
    <ul v-for="(site,index) in info.sites">
        <li>
            {{index}}----{{site.name}}
        </li>
    </ul>

</div>

</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>

    var vm = new Vue({
        el: '#app',
        data(){
            return {
                info:{
                    sites:[
                        {name:null,url:null}
                    ]
                }
            }
        },
        // data:{
        //     info:[]
        // },
        mounted(){
            axios.get('data.json').then(response=>(this.info=response.data))
        }
    })

</script>

</html>

data.json

{
  "sites": [
    { "name":"百度" , "url":"www.baidu.com" },
    { "name":"google" , "url":"www.google.com" },
    { "name":"微博" , "url":"www.weibo.com" }
  ]
}

三、Vue项目

1.环境搭建

1.1 node.js 安装

https://nodejs.org/en/download/

直接在官网上下载安装包,无脑安装下一步就行,环境变量安装时会自动配置好

在cmd中输入,node -v可以确认是否安装成功

1.2 安装cnpm

安装node时,会自动安装一个npm,npm就相当于下载包的一个工具,类似linux的yum

但是npm有时安装会很卡,所以可以安装淘宝的cnpm,两个可以切换使用,但是尽量使用npm

#-g表示,全局安装
npm install cnpm -g

#或者想要加速的话可以每次加上仓储地址,但是每次都要,很麻烦,推荐使用第一种
npm install --registry=https://registry.npm.taobao.org

1.3 安装vue-cli

cnpm install vue-cli -g

#测试是否成功
#查看可以基于哪些模板创建vue程序,通常选择webpack
vue list

1.4 创建一个vue-cli 应用程序

  • 在一个新的文件夹中使用命令行执行
#这里的myvue是项目名,可以改,第一次执行,可能会很慢,如果报错,按照提示执行相应的命令
vue init webpack myvue
  • 执行时,需要填写些信息
#项目名
? Project name myvue
#项目描述
? Project description A Vue.js project
项目作者
? Author wangzhen
构建时编译方式,选择第一个运行时编译,Runtime + Compiler: recommended for most users
? Vue build (Use arrow keys)
> Runtime + Compiler: recommended for most users
  Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - re
nder functions are required elsewhere
是否安装vue-router,选择no,后面熟悉后都可以选择yes
? Install vue-router? No
是否使用ESLint,选择no
? Use ESLint to lint your code? no
? Setup e2e tests with Nightwatch? no
是否安装测试,选择no
? Set up unit tests No
是否执行npm install,选择No, I will handle that myself
? Should we run `npm install` for you after the project has been created? (recommended)
  Yes, use NPM
  Yes, use Yarn
> No, I will handle that myself

  • 启动,执行一下命令
  #切换目录
  cd test-vue
  #安装依赖环境
  npm install
  #运行
  npm run dev
  • 运行成功之后,可以通过http://localhost:8080 访问项目

  • 用idea直接打开这个项目,然后可以通过修改config/index.js来修改端口,然后再次在idea执行,npm run dev,但是有时候执行不了,提示npm不是内部或外部命令,则是权限不够,可以通过快捷方式的属性,每次以管理员身份启动即可

  • 另外,启动出现一些错误,可能是package的版本不对,可以打开根目录下的package.json去调整

2.webpack介绍

webpack学习使用:https://www.bilibili.com/video/BV18E411a7mC?p=14

主要作用,现在很多浏览器都是基于ES5, 而Vue是基于ES6的,所以需要通过webpack将ES6打包成ES5规范的

2.1安装webpack

npm install webpack -g
npm install webpack-cli -g

#测试是否安装成功
webpack -v
webpack-cli -v

2.2 webpack结构

查看刚才idea项目里的build/webpack.*.conf.js,这个js里可以配置一些打包时的参数

比如端口,程序入口,开发生产环境配置等

  • entry:入口文件
  • output:输出,执行webpack把处理完的文件放到指定目录
  • module:模块,处理各种类型的文件
  • plugins:插件,如:热更新、代码重用等
  • reslove:设置路径指向
  • watch:监听,用于设置文件改动后直接打包

2.3 使用webpack

  1. 创建一个项目webpack-test项目

  2. 创建一个modules文件夹

  3. 添加hello.js

    //暴露一个方法
    exports.sayHi = function () {
        document.write("<h1>Hello, Vue!学习VUE真嗨森!</h1>");
    }
    
  4. 创建一个main.js

    //使用require接收hello
    var study = require("./hello");
    //调用hello的暴露的方法
    study.sayHi();
    
  5. 创建一个webpack.config.js,将模块打包

    module.exports = {
    
        entry:"./modules/main.js",
        output:{
            filename:"./js/bundle.js"
        }
    };
    
  6. 命令行执行 webpack,就会生成一个dist,里面有个js/bundle.js

  7. 新建一个index.html引用这个js/bundle.js

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <script src="dist/js/bundle.js"></script>
    </body>
    </html>
    
  8. 然后直接打开这个页面就会看到

2.4总结

上面那个项目,就很好的说明了webpack的作用,就是webpack.config.js通过entry指定js入口,然后,main.js接收所有的js,统一通过webpack将程序打包成一个ES5规范的js,然后直接引用。只不过,这些过程在vue项目已经被做好了,后面会提到

3.vue-router介绍

vue-router是Vue官方的路由管理器,

3.1 主要作用

3.2 安装

idea打开之前的myvue项目,执行安装命令

#安装vue-router, --save-dev表示保存到当前dev环境,失败了可以使用cnpm
npm install vue-router --save-dev

3.3路由使用

目录结构

  1. 创建一个组件Content.vue

    <template>
      <h1>内容页</h1>
    </template>
    
    <script>
        export default {
            name: "Content"
        }
    </script>
    
    <style scoped>
    
    </style>
    
  2. Main.vue

    <template>
      <h1>首页</h1>
    </template>
    	
    <script>
        export default {
            name: "Main"
        }
    </script>
    
    <style scoped>
    
    </style>
    
  3. 创建路由管理router.js

    先从vue-router导入VueRouter,然后安装路由Vue.use(VueRouter),最后将新的配置好的路由通过export default new VueRouter({})导出

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Content from '../components/Content'
    import Main from '../components/Main'
    
    //安装路由
    Vue.use(VueRouter);
    
    
    //配置导出路由
    export default new VueRouter({
      routes:[
        {
          path:'/content',
          name:'content',
          component:Content
        },
        {
          path:'/main',
          name:'main',
          component:Main
        }
      ]
    });
    
    
  4. 程序入口(前面讲到,可以在webpack配置文件中修改入口)main.js导入路由,分为两步

    • 程序入口导入路由

    • Vue对象(这个vue对象时全局唯一)中配置路由

      import Vue from 'vue'
      import AppTest from './App'
      //1.导入路由,自动扫描里面的配置文件
      import router from './router'
      
      Vue.config.productionTip = false
      
      new Vue({
        el: '#app',
        //2. 配置路由
        router,
        a:{
      
        },
        components: { AppTest },
        template: '<AppTest/>'
      })
      
  5. 在APP.vue中使用路由

    • router-link,可以认为是<a>标签,通过to,可以跳到指定的路由
    • router-view,用于展示页面
    <router-link to="/main">首页</router-link>
    <router-link to="/content">内容页</router-link>
    <router-view></router-view>
    
    <template>
      <div id="app">
        <h1>Vue学习</h1>
        <router-link to="/main">首页</router-link>
        <router-link to="/content">内容页</router-link>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    
    export default {
      name: 'App'
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

4. Vue项目搭建

4.1初始化项目

# 通过vue-cli提供的webpack模板初始化项目,一路选择no
vue init webpack hello-vue
# 进入工程
cd hello-vue
# 安装路由
npm install vue-router --save-dev
# 安装element-ui
npm i element-ui -S
# 安装SASS 加载器,注意SASS可能自动安装的版本太高了,如果报错需自行到package.json中调整成7.3.1
npm install sass-loader node-sass --save-dev
# 启动测试
npm run dev

4.2 实现登录功能

实现流程和路由使用是一样的,创建登录组件,然后创建路由管理router.js,然后入口main.js引用路由,然后主程序app.vue使用标签展示页面

项目详情参考https://github.com/MilesWang-Zhen/hello-vue

5.其他知识点

5.1 路由嵌套

就是路由底下还可以写路由,通过children嵌套,下面就是在main下面嵌套两个页面/user/profile/,/user/list

export default new VueRouter({
  mode:'history',
  routes:[
    {
      path:'/main/:username',
      component:Main,
      props:true,
      children:[
        {
          path:"/user/profile/:id",
          name:"UserProfile",
          component:UserProfile,
          props:true
        },
        {
          path:"/user/list",
          component:UserList
        }
      ]
    },
    {
      path:'/login',
      component:Login
    },
    {
      path:'/goHome',
      redirect:'/Login'
    },
    {
      path:'*',
      component:NotFound
    }
  ]
});

5.2 参数传递

  1. 可以在router-link的to属性中添加参数,name为路由中配置UserProfile,params为参数

    <router-link :to="{name:'UserProfile', params:{id:1}}">个人信息</router-link>
    
  2. 然后在路由配置中的path添加上id

    path:"/user/profile/:id"
    
  3. 然后在Profile.vue中可以使用,有两种使用方式

  • 第一种,注意{{$route.parms.id}}需要被被其他标签包裹,不能直接写在<template>

    ```html
    <template>
    <!-- 所有元素,一定不能在根节点下,否则会报错 -->
      <div>
        <h1>个人信息</h1>
        {{$route.parms.id}}
      </div>
    </template>
    <script>
        export default {
          name: "UserProfile"
        }
    </script>
    ```
    
  • 第二种,需要在路由中配置props:true,然后再组件中使用props:[‘id’]接收,最后再使用

    ``` html
    <template>
      <div>
        <h1>个人信息</h1>
        {{id}}
      </div>
    </template>
    <script>
        export default {
          props:['id'],
          name: "UserProfile"
        }
    </script>
    ```
    

5.3页面重定向

在路由router.js中直接加上这段配置,然后通过配置/goHome,点击之后就会重定向到/Login页面

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

5.4 去除访问地址中的#号

可以修改路由的mode, mode默认是hash模式,hash模式会带个#,可以改成history

  mode:'history',

5.5简单处理404

添加一个NotFound组件,然后在路由中监听所有path的配置,一般写在最后,如果前面的都没进,就会到404页面

    {
      path:'*',
      component:NotFound
    }

5.6钩子函数

以Profile组件为例

<template>
  <div>
    <h1>个人信息</h1>
    {{id}}
  </div>
</template>

<script>
    export default {
      props:['id'],
      name: "UserProfile",
      beforeRouteEnter:(to, from, next)=>{
        console.log("进入路由");
        next(vm => {
          vm.getData();
        });
      },
      beforeRouteLeave:(to, from, next)=>{
        console.log("离开路由");
        next();
      },
      methods:{
        getData:function () {
          this.axios({
            method:'get',
            url:'http://localhost:8080/static/mock/data.json'
          }).then(function (response) {
            console.log(response);
          })
        }
      }
    }
</script>

<style scoped>

</style>

beforeRouteEnter在进入路由之前执行,beforeRouteLeave在离开路由之前执行,一定需要写next(),不然就走不到下一个钩子了,有点类似于java过滤器

参数解释:

5.7在钩子函数中使用axios

  1. 安装axios, 当然使用axios的使用,也可以通过script的方式

    cnpm install axios -s
    
  2. main.js 中引用Axios

    import axios from 'axios'
    import VueAxios from 'vue-axios'
    
    Vue.use(VueAxios, axios)
    
  3. 创建测试数据

    注意data.json需要放在static中才能直接访问到

    {
      "sites": [
        { "name":"百度" , "url":"www.baidu.com" },
        { "name":"google" , "url":"www.google.com" },
        { "name":"微博" , "url":"www.weibo.com" }
      ]
    }
    
  4. axios获取数据

    在组件中添加methods属性, 然后在next()里直接拿到Vue对象vm(vm只是个变量名,可随意写),然后调用methods中的getData(),可以获取response

     export default {
          props:['id'],
          name: "UserProfile",
          beforeRouteEnter:(to, from, next)=>{
            console.log("进入路由");
            next(vm => {
              vm.getData();
            });
          },
          beforeRouteLeave:(to, from, next)=>{
            console.log("离开路由");
            next();
          },
          methods:{
            getData:function () {
              this.axios({
                method:'get',
                url:'http://localhost:8080/static/mock/data.json'
              }).then(function (response) {
                console.log(response);
              })
            }
          }
        }
    

参考资料

B站学习视频:https://www.bilibili.com/video/BV18E411a7mC
学习笔记:https://blog.csdn.net/jzandth/category_10414568.html
Vue生命周期
image.png
image.png
image.png
image.png