vue01

vue01 : vue基本语法

vue02 : 博彩项目采用vue方式实现

vue03 : 博彩项目采用vue方式实现

传统的Web项目 : 后台逻辑,html数据的渲染thymeleaf,jsp

web项目: 后台程序只负责提供数据, 前端负责去展现html数据

介绍

简单来说,Vue是一套渲染UI的强大前端框架。

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

主要特性:

  • 学习曲线非常平缓,只要有html/css,js基础即可上手
  • 响应式的支持,让我们从传统的JQuery的面向DOM编程,转变为面向数据编程
  • 丰富的语法支持
  • 优雅的单文件组件
  • 完善的组件动画支持
  • 成熟的生态,比如vue-cli,VueRouter,Vuex等相关配套的工具

其中,最重要最核心的特性就是:响应式和组件化。

安装

官方文档:https://cn.vuejs.org/

  • 通过<script></script>引用

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    
  • 通过vue-cli安装全套开发环境,项目开发推荐

快速尝鲜

通过一个简单的例子,来快速感受一下Vue的特性。

例子中使用:值填充以及响应式的UI刷新,

  • v-model实现输入项双向绑定特性

  • v-for循环

  • v-if条件判断

  • v-on:click单击事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
    {{msg}}
    <input type="text" v-model="username"><span>{{username}}</span>
    <ul>
        <li v-for="item in list">{{item}}</li>
    </ul>
    <h3 v-if="isShow">我在某些条件下才显示</h3>
    <button @click="isShow=!isShow">点我隐藏上面的文字</button>
    
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data:{
            msg: "我是Vue",
            list:[
                'a', 'b', 'c'
            ],
            isShow: true,
            username: "aaaa"
        }
    });
    setTimeout(()=>{
        vm.msg = "我的值被改变了,会响应式的刷新到UI上";
        vm.list.push("dd");
    }, 2000)
</script>
</body>
</html>

Vue实例

数据和方法

每一个Vue实例,都可以有自己的数据和自定义方法。自定义方法一般用来获取数据或者对数据进行处理。

let vue = new Vue({
       el: "#app",
       data: {
           content: "aaa"
       },
       template: "<div><button v-on:click="handleClick">点我让content变化</button> : {{content}}</div>",
       methods: {
           handleClick(){
               this.content = "bbb"
           }
       }
    });

生命周期钩子

所谓的生命周期其实就像我们人,从出生到成长到死亡的过程一样.在Vue中生命周期指的是Vue实例从初始化,创建,显示,更新以及销毁的整个过程,而生命周期钩子指的是每个过程都有一个回调函数,Vue中把回调函数称为钩子。

  • beforeCreate : 开始创建实例
  • created : 实例创建出来了,vue的实例基本上被初始化
  • beforeMount : 模版与数据相结合,页面渲染之前,执行的函数
  • mounted: 模版和数据结合完成,会将Vue实例挂载到dom树上
  • beforeDestroy : 实例要被回收的时候执行
  • destroyed : 实例回收完成的时候调用
  • beforeUpdate: 数据发生改变,还没有渲染之前
  • updated : 渲染完成

再次回顾一下什么是Vue生命周期钩子? 生命周期钩子就是Vue实例在某个时间点自动执行的回调函数.我们常用的生命周期钩子有: created,mounted

<script>
    let vm = new Vue({
        el:'#app',
        template:'<span>{{msg}}</span>',
        data:{
            msg:'hahaha'
        },
        beforeCreate(){
            console.log("beforeCreate...")
        },
        created(){
            console.log("created...")
        },
        beforeMount(){
            console.log("beforeMount..."+this.$el.innerHTML)
        },
        mounted(){
            console.log("mounted..."+this.$el.innerHTML)
        },
        beforeDestroy(){
            console.log("beforeDestory...")
        },
        destroyed(){
            console.log("destoryed...")
        },
        beforeUpdate(){
            console.log("beforeUpdate...")
        },
        updated(){
            console.log("updated")
        }
    })
</script>

计算属性

计算属性和方法都可以对数据进行处理。但是计算属性有基于依赖数据的智能缓存,当计算属性所依赖的值发生改变,计算属性才会重新计算, 所以性能更高,我们应该优先考虑使用。

如果是普通的方法实现相同的功能,每当页面数据任何数据发生改变的时候,方法都会被执行一次

let vue = new Vue({
       el: "#app",
       data: {
           firstName: "Xiao",
           lastName: "Kaikai",
           age:30
       },
       computed: {
           // 计算属性有基于依赖数据的缓存
          fullName(){
              console.log("计算属性执行了一次");
              return this.firstName + this.lastName;
          }
       } ,
       methods: {
         getFullName(){
             console.log("自定义方法执行了");
             return this.firstName + this.lastName;
         }
       }
    });

侦听器

侦听器可以用来侦听数据的改变. 如果一个功能,方法能实现,计算属性能实现,侦听器也能实现,我们应该优先选择计算属性

  let vm = new Vue({
        el:'#app',
        data:{
            firstName:'Kaikai',
            lastName:'Xiao',
            age:30,
            fullName:"Kaikai Xiao"
        },
        methods:{
          getFullName(){
              console.log("getFullName执行了一次运算")
              return this.firstName + ' ' + this.lastName;
          }
        },
        watch:{
            firstName(newVal,oldVal){
                this.fullName = this.firstName + this.lastName;
                console.log('newVal:'+newVal+" oldVal:"+oldVal);
            },
            lastName(){
                this.fullName = this.firstName + this.lastName;
            }
        }
	}

class动态绑定

Vue允许我们给DOM元素动态绑定一些class。

<body>
       <div id="app">
           <div class="c1" :class="{c2:isShow,c3:isShow}" @click="isShow=!isShow" >{{name}}</div>
		   class动态绑定数组的语法	
           <div class="c1" :class="classes" @click="isShow=!isShow" >{{name}}</div>
       </div>
</body>
<script>
    let vm = new Vue({
        el:'#app',
        data:{
            name:'zhangsan',
            isShow:true,
            classes:['c1','c2','c3']
        }
    });
</script>
<style>
    .c1{
        font-size: 10px;
        color: green;
        background-color: yellow;
    }
    .c2{
        font-size: 30px;
    }
    .c3{
        background-color: red;
    }
</style>

条件渲染

v-show

<div v-show="isShow">页面内容v-show</div>

v-if

v-else-if

v-else

<div id="app" >
    <div v-if="isLogin">您好,刘德华</div>
    <div v-else><button @click="isLogin=true">登录</button></div>

    <!--对于需要频繁切换显示隐藏的场景,用v-show,因为性能更高-->
    <!--<div v-show="isLogin">您好,刘德华2</div>-->
</div>
<script>
    let vue = new Vue({
       el: "#app",
       data: {
           isLogin: false
       }
    });
</script>

列表渲染

当我们去使用v-for的时候,最好去给它指定一个唯一的key值,这样的会方便vue复用dom节点,从而提高性能

遍历数组

使用的语法: v-for="(item,index) in 数组" 若写了:key,那么它的值需要是唯一的值

<div id="app" >
    <div>最好吃的水果:</div>
    <div v-for="item in list">{{item}}</div>
    <input type="text" v-model="fruit"><button @click="handleClick">添加</button>
    <div>
        <button @click="handleDelete">删除第</button><input type="text" v-model="index">个
    </div>
</div>
<script>
    let vm = new Vue({
       el: "#app",
       data: {
           list:[
               "苹果","西瓜","哈蜜瓜"
           ],
           fruit: "",
           index: 0
       },
        methods:{
            handleClick(){
                this.list.push(this.fruit);
                this.fruit = "";
            },
            handleDelete(){
                this.list.splice(this.index, 1);
            }
        }
    });
</script>

注意:当我们去修改数组的时候,不能使用下标的方式,否则数据添加进去了,页面不会刷新,我们需要借助数组提供的一些方法来修改,我们常用的数组方法有:

  • push : 添加元素
  • pop : 取出末尾元素
  • splice : 根据角标删除元素
  • sort : 排序
  • forEach : 循环处理

遍历对象

v-for="(item,key,index) in 对象"

<div v-for="item,key,index in user">{{item}}--{{key}}--{{index}}</div>
let vm = new Vue({
        el:'#app',
        data:{
            user:{
                username:"haha",
                password:123,
                age:100
            }
        }
    });

注意: 我们如果直接添加一个属性,页面上并不会跟着刷新

Vue中的set方法

当我们去修改某一个对象的内容的时候,由于vue中并不知道对象内容发生了改变,所以也就不会重新渲染了,若想当对象内容发生改变页面重新渲染,我们需要借助Vue给我们提供的一下方法

使用全局的方法: Vue.set(对象,改变的key,改变的值)

使用实例的方法: vm.$set(对象,改变的key,改变的值)

数组中使用set方法: vm.$set(对象,要改变的下标,改变的值)

ToDoList

用上面学的语法,实现一个ToDoList。

<body>
       <div id="app">
            <h3>添加今日要完成任务</h3>
            <input type="text" v-model="currentInput" /><button @click="handleAdd">添加</button>
           <ul>
               <li v-for="item in todos" :class="{done:item.isDone}" >
                   {{item.text}}
                   <button @click="handleComplete(item)" >标记完成</button>
                   <button @click="handleDelete(item)">删除</button>
               </li>
           </ul>
       </div>
</body>
<style>
    .done{
        background-color: red;
    }
</style>
<script>
    
    let vm = new Vue({
        el:'#app',
        data:{
           todos:[],
           currentInput:""
        },
        methods:{
            handleAdd(){
                //判断是否为空
                if(this.currentInput === ""){
                    return ;
                }
                //检查是否有重复的内容
                for(let i=0;i<this.todos.length;i++){
                    //数组中的每一项
                    let item = this.todos[i];
                    //判断是否有重复
                    if(item.text === this.currentInput){
                        return;
                    }
                }
                //获取输入项的内容,将输入项的内容存到todos
                this.todos.push({text:this.currentInput,isDone:false});
                //清空输入项的内容
                this.currentInput = ""
            },
            handleComplete(item){
                item.isDone = true;
            },
            handleDelete(item){
                //从todos中删除这个item
                let index = this.todos.indexOf(item);
                //调用数组中删除的方法
                this.todos.splice(index,1);
            }
        }
    });
</script>
</html>

组件

组件是Vue的核心之一,任何一个大的系统都可以由多个小的组件共同构成。组件的复用性,也大大提高了前端开发的效率。

组件注册

组件的注册有全局注册和局部注册两种方式。

全局注册: 注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中

全局组件

<script>
    /*定义一个全局组件*/
    Vue.component('title-bar',{
        template:`<div><h1>首页标题栏</h1></div>`
    });
    /*定义一个全局组件*/
    Vue.component('MenuBar',{
        template:`<div><h1>底部菜单栏</h1></div>`
    });

    let vm = new Vue({
        el:'#app'
    });
</script>

局部组件

局部注册: 全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

<script>
    <!--定义局部组件-->
    let TitleBar = {
        name:'title-bar',
        template:`<div><h1>{{title}}标题部分</h1></div>`,
        data(){
            return {
                title:'首页'
            }
        }
    }

    /*定义一个局部组件*/
    let MenuBar = {
        name:'menu-bar',
        template:`<div><h1>底部菜单部分</h1></div>`
    }
    //根实例
    let vm = new Vue({
        el:'#app',
        components:{
            TitleBar,
            MenuBar
        }
    });
</script>

父子组件数据通信

父子组件之间往往不是独立的,需要进行数据的通信。从父到子,用props;从子到父,用$emit。

<div id="app">
    <ul>
        <li v-for="item,index in list"><todo-item :content="item" :index='index' @delete-item="handleDeleteItem"></todo-item></li>
    </ul>
    <child :text="text"></child>
</div>
<script>
    // 全局注册
    Vue.component("todo-item", {
        props:['content','index'],
        data() {
            return {

            }
        },
        template: "<div @click='handlerClick'>{{content}}</div>",
        methods: {
            handlerClick(){
                this.$emit("delete-item", this.index);
            }
        }
    });

    // 子组件不要去直接修改父组件的数据
    Vue.component("child", {
        props:['text'],
        data() {
            return {
                myText: this.text
            }
        },
        template: "<div @click='changeText'>{{myText}}</div>",
        methods: {
            changeText(){
                this.myText = "修改了的文字";
            }
        }
    });


    let vue = new Vue({
        el: "#app",
        data: {
            list: [
                "吃饭", "睡觉", "打豆豆"
            ],
            text: "文字"
        },
        methods:{
            handleDeleteItem(index){
                this.list.splice(index, 1);
            }
        }
    });
</script>

组件绑定原生事件

如果我们在自定义组件上绑定事件是没有效果的,因为组件上定义的事件都是自定义的,想要触发需要我们在子组件内部调用$emit派发.但是这样做又很麻烦,所以当我们想使用点击事件,我们可以使用Vue提供的绑定原生事件方式,我们只需要使用@click.native

<div id="app">
    <child :text="text" @click.native="handleChildClick"></child>
</div>

<script>
 //全局组件
    Vue.component('child',{
        template:`<div>子组件的内容展示</div>`
        /*template:`<div @click="handleChildClick">子组件的内容展示</div>`,
        methods:{
            handleChildClick(){
                console.log("child click");
                this.$emit('click');
            }
        }*/
    });
    //根实例 ,父组件
    let vm = new Vue({
        el:'#app',
        methods:{
            handleFatherClick(){
                console.log("father click")
            }
        }
    });
</script>

组件插槽

有时候我们组件的内容是不确定的,我们定义组件的时候使用slot留出空白,外界使用的时候动态插入,这就是插槽。

<body>
       <div id="app">
           <child >
               <div slot="header">header</div>
               <!--<div slot="footer">footer</div>-->
           </child>
       </div>
</body>

<script>
    //定义子组件
    Vue.component('child',{
       template:`<div>
                    <slot name="header"></slot>
                    <div>内容不变</div>
                    <slot name="footer">默认页脚</slot>
                 </div>
                `
    });

    //根实例 ,父组件
    let vm = new Vue({
        el:'#app',
    });
</script>

动态组件:is

动态组件可以非常方便的切换几个不同的组件,而且支持缓存。

<body>
       <div id="app">
           <component :is="currentName"></component>
           <button @click="handleClick('home')">首页</button>
           <button @click="handleClick('my')">我的</button>
       </div>
</body>

<script>
    Vue.component('home',{
        template:`<div>这是网站首页的内容</div>`
    });

    Vue.component('my',{
        template:`<div>这是我的个人页面</div>`
    })

    //根实例 ,父组件
    let vm = new Vue({
        el:'#app',
        data:{
            currentName:'home'
        },
        methods:{
            handleClick(name){
                this.currentName = name;
            }
        }
    });
</script>

Vue-cli

以上内容是项目开发中常用的基础知识点。但是做项目开发,我们需要考虑一下几点:

  1. 编写的代码需要打包工具进行打包压缩,图片处理
  2. 为了效率,希望有一个HotReload功能,不用手动刷新
  3. Vue单文件组件的支持
  4. 第三方JS编译器的使用,如babel
  5. 第三方CSS预处理器的使用,如stylus,sass
  6. 第三方插件的使用,如ESLint。PostCSS

而Vue-cli就为了解决上面的问题而生的,它给我们打包好了所有能用到的好工具,提供一个开箱即用的项目开发环境。所以,我们需要用它来创建项目。

vue-cli官网:https://cli.vuejs.org/,官网写的是3.0版本的使用,2.xx才是稳定版。

vue-cli github主页:https://github.com/vuejs/vue-cli

创建工程

vue-cli的github网站默认是3.0的测试版本分支,需要切换为主分支。

npm install -g vue-cli
vue init webpack xxx

?Project name lottery
?Project description this is a niubility project
?Author xiaokaikai
?Vue build (选择一种构建的形式)
> Runtime + Compiler: recommended for most users
?Install vue-router?(Y/n) Y  --这里说是否安装路由插件
?Use ESLint to lint your code? N-- 是否检查代码格式
?Pick an ESLint preset Standard  -- 选择一种代码检查的规范
?Set up unit tests  N  是否进行单元测试
?Setup e2e tests with Nightwatch N 是否使用e2e工具进行构建
?Should we run 'npm install' for you after the project has been created? npm --选择npm方式安装

输入完成之后,工具就开始构建我们的工程啦!

工程目录结构

  • build:构建相关目录
  • config:开发相关配置
  • src:要编写的代码
  • static:不需要webpack处理的静态文件,比如压缩后的资源,可以直接访问

Vue-Router

传统的路由是后端来做,简单说就是请求一个url,后端根据请求的参数内容渲染出相应的html返回。由于JS可以感知到浏览器URL的变化,因此可以做到在url变化的时候去加载不同的DOM内容,这就是前端路由,和后端没有任何关系了。

单页应用(SPA)的用户体验比传统的多页应用要好很多,所以越来越多的公司开始尝试单页应用。单页应用就将原来的多个页面做成一个html,JS根据url的变化切换DOM的内容。这样不用再去请求服务器的整个html内容,只需要请求对应的json数据,因此速度会快很多。

Vue-Router为前端路由提供了封装和简化,并结合组件的使用。让我们可以一个url对应一个组件,轻松编写大型的SPA应用。

<router-view> 显示当前路径所对应的组件内容
<router-link to="要跳转去的组件的路径">

总结:

根实例 : let vm = new Vue({参数})
el
template
data
methods
computed
watch
props
生命周期钩子

vue中属性
v-model
v-show
v-if
v-else-if
v-else

v-for
v-html
v-text

使用属性:  :属性名称

绑定事件:@事件名称 

全局组件和局部组件

父子组件之间通讯
父-->子 : props
子 --> 父: $emit(事件名称)

@click.native 组件绑定原生事件

动态组件: <component :is=组件的名称
原文地址:https://www.cnblogs.com/xiaocongcong888/p/9435892.html