Vue入坑篇(一) --详细

一.什么是Vue.js?

1. 前端三大流行框架: Vue.js   Angular.js   React.js

2.Vue.js是目前最火的前端框架,React.js是最流行的前端框架(React.js可以进行网页开发和手机App的开发,Vue.js也是可以的,但是Vue.js进行手机App开发需要借助Weex)。总的来说Vue.js是一套用于构建用户界面的框架,只关注视图层。方便于第三方类库以及既有项目整合来做大项目。

          3.Vue的核心概念:

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

科普前端发展:前端提高开发效率的发展历程:原声JS-->JQuery之类的类库--->前端模板引擎--->Angular.js/Vue.js(能够帮我们减少不必要的DOM操作;提高渲染效率;双向数据绑定的概念{通过框架提供的指令,我们前端程序员只需要关心数据的业务逻辑,不再关心DOM是如何渲染的了})


了解:框架和库的区别:

框架:有一套完整的解决方案;对项目侵入性较大;项目如何需要更换框架,则需要重新架构整个项目。

库(插件):提供某一个小功能,对项目入侵性小,如果某个库无法完成某些需求,可以很容易切换到其他实现需求。

了解:MVC和MVVM之间的区别:

MVC:是后端的分层开发的概念

MVVM:是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端

的视图层分为了三部分,Model,View,VM ViewModel


二.了解和区分MVC以及MVVM

MVC:

View视图层:用户操作页面,每一个操作都会进行后端的网络请求,发送给app.js {V层}

app.js:项目的入口模块(一切请求都要进入这里进行处理。)

 

router.js: 路由器分发处理模块(分发路由)

Controller:业务逻辑处理层。(封装了一些业务逻辑的代码) {两者组成Controller}

 

Model: 操作数据库,执行对应的SQL语句,进行数据的CRUD. {M层}

Vue入坑篇(一) --详细

 

MVVM:前端视图层的开发思想,主要把每个页面,分成了M,V和VM,其中VM是MVVM思想的核心。VM是M和V之间的调度者。

M:保存每个页面中的单独数据(从服务器上发送的数据)。

V:每个页面中的HTML结构。

VM:调读者,分割V和M。每次存取数据都要经过VM的代办。

取数据:M-->VM-->V

存数据:V--->VM-->M

MVVM思想的好处:前端页面使用MVVM的思想,让我们开发更高效,因为MVVM提供了数据的双向绑定。

那么来介绍一下Vue.js的数据双向绑定:vue是一个mvvm框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。数据双向绑定一般是对UI控件来说。

 

案例1:

<body>

<!--Vm实例所控制的这个元素区域,就是我们的V-->
<div id="app"> 
<p>{{msg}}</p>

</div>



<script>
//注意:我们new出来的这个vm对象,就是我们MVVM中VM调度者。
var vm=new Vue({
//表示当前我们new的这个Vue实例,要控制页面上的哪个区域(以id区分)
     el:'#app', 
//这里的data就是MVVM中M,专门用来保存每个页面的数据的。
//通过Vue提供的指令,很方便的就能把数据渲染到页面上,不必再手动操作DOM元素了【前端的Vue之类框架,不提倡我们去手动操作DOM元素了】
     data:{ 
             msg:'欢迎学习Vue',
           }

})


</script>

</body>

三.Vue.js的基础指令

1.插值表达式:{{}}  


<script src="vue-2.4.0.js"></script>
<script>
    //new一个vm实例
    var vm=new Vue({
        el:'#area',
        data:{
            msg:'关注John_Zhou得福利!!',
            msg2:'<h4>我是h4我最大!</h4>',
            msg3:'input标签',
        },
        methods:{
            /*
            //ES6以前的写法
            show:function(){
                alert("v-on事件绑定机制成功!!")
            }
            */
            //ES6的写法
            show(){
                alert("v-on事件绑定机制成功!!")
            },
        }
  
})
</script>
<!--一般不单独使用插值表达式,因为如果vue.js加载过慢,造成页面刷新时msg的值闪烁问题 -->
<p>{{msg}}</p>

2.v-cloak  (解决插值表达式闪烁问题)

<!-- v-cloak指令 可以解决闪烁问题-->
<p v-cloak>{{msg}}</p>

3.v-text 

<!-- v-text 本身没有插值闪烁问题 -->
<!-- v-text里的内容会覆盖掉标签里的所有内容,插值表达式{{}}只会覆盖掉自己占位符上的内容 -->
<p v-text="msg">===</p>

4.v-html  (用于属性值里面有标签的情况下,保证标签字符串不会被当字符串内容在页面输出)

<div v-html="msg2"></div>
<!--HTML页面显示内容等同于: -->
<div>
    <h4>我是h4,我最大!</h4>
</div>

5.v-bind  (用于绑定对象属性,即:去掉插值表达式{{}},可以直接写vm实例中data的属性名来取得值,缩写 : )

<input type="text" v-bind:value="msg3">
<!--等同于: -->
<input type="text" :value="msg3">

6.v-on  (事件绑定机制指令,缩写  @ )

<!-- show是vm实例methods属性里的方法 --> 
<input type="button" value="点击事件1" v-on:click="show">
<!-- 等同于 --> 
<input type="button" value="点击事件1" @click="show">

案例2:跑马灯实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="vue-2.4.0.js"></script>
<body>
<div id="app">
  <input type="button"  value="浪起来" @click="lang">
  <input type="button"  value="别浪" @click="stop">
  <h4>{{msg}}</h4>
</div>
<script>
  //在vm实例中,如果想调用data上的数据或者是调用实例方法,必须通过this.属性名来调用和获取。this表示当前vm实例
  var vm=new Vue({
    el:'#app',
    data:{
      msg:'关注John_Zhou,得福利!!!',
      intervalID:null,  //用于定时器
    },
    methods:{
      lang() {
        //不能开启多个定时器
        if(this.intervalID!=null) return;
        //setInterval(方法,间隔时间)
        //=>表示当前方法内的this等同于外部的this,外部this指向的是vm实例
        /*
        * 箭头函数修复了this的指向, this 总是指向词法作用域, 也就是上一层调用者的obj(上一层的实例):
        * 因为setInterval()方法内的this指向的是lang()层的对象实例,但是lang()层内部没有实例,会造成this等于undefined
        * 使用箭头函数可以有效避免此类错误。
        * */
        this.intervalID=setInterval( () => {
          //从0位置开始截,截得长度为1
          var start=this.msg.substr(0,1);
          //从1位置开始截,截取到最后位置
          var end=this.msg.substr(1);
          /*注意:vm实例会自动监听自身得变化,一旦data数据发生变化,
          会自动把数据同步到页面上去(不用自己dom操作添加了)。
          好处:让程序员只需要关注如何修改数据,不必关心如何重新渲染页面DOM。
          */
          //新字符
          this.msg=end+start;
        },400)
      },
      stop(){
        //终止定时器
        clearInterval(this.intervalID);
        //每当清除定时器后,赋值intervalID为null,以便下次开启新的定时器。
        this.intervalID==null;
      },
    },

  })
</script>
</body>
</html>

7.事件修饰符

.stop  阻止冒泡       ï¼ˆå†’泡:即由点击元素向外触发父元素的v-on绑定的事件)

.prevent 阻止默认事件(阻止标签默认会触发的事件,如点击<a>标签时阻止<a>标签自带的跳转事件)

.capture 捕获模式 (捕获模式:与冒泡相似,不过方向是反。即由点击元素向内触发子元素的v-on绑定的事件)

.self 只有点击本体元素时才触发绑定的事件,子元素的冒泡或父元素的捕获都不能触发此元素绑定的事件。

.once 事件只触发一次

参考代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="vue-2.4.0.js"></script>
  <style>
    .inner {
      height: 150px;
      background-color: darkcyan;
    }

    .outer {
      padding: 40px;
      background-color: red;
    }
  </style>
</head>

<body>
  <div id="app">

    <!-- 使用  .stop  阻止冒泡 -->
     <div class="inner" @click="div1Handler">
      <input type="button" value="戳他" @click.stop="btnHandler">
    </div>

     <!--使用 .prevent 阻止默认行为 -->
     <a href="http://www.baidu.com" @click.prevent="linkClick">有问题,先去百度</a>

    <!-- 使用  .capture 实现捕获触发事件的机制 -->
    <div class="inner" @click.capture="div1Handler">
      <input type="button" value="戳他" @click="btnHandler">
    </div>

    <!-- 使用 .self 实现只有点击当前元素时候,才会触发事件处理函数 -->
    <div class="inner" @click="div1Handler">
      <input type="button" value="戳他" @click="btnHandler">
    </div>

    <!-- 使用 .once 只触发一次事件处理函数 -->
    <a href="http://www.baidu.com" @click.prevent.once="linkClick">有问题,先去百度</a> 


    <!-- 演示: .stop 和 .self 的区别 -->
    <div class="outer" @click="div2Handler">
      <div class="inner" @click="div1Handler">
        <input type="button" value="戳他" @click.stop="btnHandler">
      </div>
    </div>

    <!-- .self 只会阻止自己身上冒泡行为的触发,并不会真正阻止 冒泡的行为 -->
    <div class="outer" @click="div2Handler">
      <div class="inner" @click.self="div1Handler">
        <input type="button" value="戳他" @click="btnHandler">
      </div>
    </div>

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        div1Handler() {
          console.log('这是触发了 inner div 的点击事件')
        },
        btnHandler() {
          console.log('这是触发了 btn 按钮 的点击事件')
        },
        linkClick() {
          console.log('触发了连接的点击事件')
        },
        div2Handler() {
          console.log('这是触发了 outer div 的点击事件')
        }
      }
    });
  </script>
</body>

</html>

8.v-model   (用于实现数据的双向绑定)

v-bind是把M中的数据拿到V中,但是在V中修改的数据,并不能同步到M中。所以v-bind是单向数据绑定。

v-model是双向数据绑定,无论M中修改的数据还是V中修改的数据都能同步到对方内部。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="vue-2.4.0.js"></script>
</head>

<body>
<div id="area">
  双向绑定:<input type="text" v-model="msg" style="width: 80%;"><br>
  单向绑定:<input type="text" :value="msg" style="width: 80%;">
</div>
<script>
  //new一个vm实例
  var vm=new Vue({
    el:'#area',
    data:{
      msg:'关注John_Zhou得福利!!',
      msg2:'<h4>我是h4我最大!</h4>',
      msg3:'input标签',
    },
    methods:{
      /*
      //ES6以前的写法
      show:function(){
          alert("v-on事件绑定机制成功!!")
      }
      */
      //ES6的写法
      show(){
        alert("v-on事件绑定机制成功!!")
      },
    }

  })
</script>
</body>

</html>

.9.Vue属性绑定来实现class类样式和style行内样式

案例3:属性绑定后class类样式使用

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    .red {
      color: red;
    }

    .thin {
      font-weight: 200;
    }

    .italic {
      font-style: italic;
    }

    .active {
      letter-spacing: 0.5em;
    }
  </style>
</head>

<body>
  <div id="app">
   <h1 class="red thin">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 第一种使用方式,直接传递一个数组,注意: 这里的 class 需要使用  v-bind 做数据绑定 -->
   <h1 :class="['thin', 'italic']">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在数组中使用三元表达式 -->
    <h1 :class="['thin', 'italic', flag?'active':'']">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在数组中使用 对象来代替三元表达式,提高代码的可读性 -->
    <h1 :class="['thin', 'italic', {'active':flag} ]">这是一个很大很大的H1,大到你无法想象!!!</h1>

    <!-- 在为 class 使用 v-bind 绑定 对象的时候,对象的属性是类名,由于 对象的属性可带引号,也可不带引号,所以 这里我没写引号;  属性的值 是一个标识符 -->
    <h1 :class="classObj">这是一个很大很大的H1,大到你无法想象!!!</h1>


  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: true,
        classObj: { red: true, thin: true, italic: false, active: false }
      },
      methods: {}
    });
  </script>
</body>

</html>

案例4:属性绑定后style行内样式

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- 对象就是无序键值对的集合 -->
    <h1 :style="styleObj1">这是一个h1</h1>

    <h1 :style="[ styleObj1, styleObj2 ]">这是一个h1</h1>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        styleObj1: { color: 'red', 'font-weight': 200 },
        styleObj2: { 'font-style': 'italic' }
      },
      methods: {}
    });
  </script>
</body>

</html>

10.Vue指令之 v-for  和 key属性

list集合定义在data中,<p v-for="(item,i) in list">{{item}}</p> (可遍历数组,对象数组,迭代数字) 

v-for遍历单个对象:(val值,key键,index索引)的形式。<p v-for="(value,key,index) in 对象名"></p>

key属性:只能是number或string,用于唯一标识,以便增加节点时,Vue.js的重用和重新排序DOM树。

案例4:遍历普通数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
     <p>{{list[0]}}</p>
    <p>{{list[1]}}</p>
    <p>{{list[2]}}</p>
    <p>{{list[3]}}</p>
    <p>{{list[4]}}</p>

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

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list: [1, 2, 3, 4, 5, 6]
      },
      methods: {}
    });
  </script>
</body>

</html>

 

案例5:遍历对象数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

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

  <script>
    // 创建 Vue 实例,得到 ViewModel
    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>
</body>

</html>

案例6:遍历单个对象

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- 注意:在遍历对象身上的键值对的时候, 除了 有  val  key  ,在第三个位置还有 一个 索引  -->
    <p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        user: {
          id: 1,
          name: '托尼·å±Žå¤§é¢—',
          gender: '男'
        }
      },
      methods: {}
    });
  </script>
</body>

</html>

案例7:迭代数字

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- in 后面我们放过  普通数组,对象数组,对象, 还可以放数字 -->
    <!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 -->
    <p v-for="count in 10">这是第 {{ count }} 次循环</p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>
</body>

</html>

案例8:key属性的使用。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <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>

    <!-- 注意: v-for 循环的时候,key 属性只能使用 number获取string -->
    <!-- 注意: key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值 -->
    <!-- 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值 -->
    <p v-for="item in list" :key="item.id">
      <input type="checkbox">{{item.id}} --- {{item.name}}
    </p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        id: '',
        name: '',
        list: [
          { id: 1, name: '赵倩' },
          { id: 2, name: '周武' },
          { id: 3, name: '虞姬' },
          { id: 4, name: '张三' },
          { id: 5, name: '王六' }
        ]
      },
      methods: {
        add() { // 添加方法
          this.list.unshift({ id: this.id, name: this.name })
        }
      }
    });
  </script>
</body>

</html>

11.v-if 和 v-show 指令

v-if:创建和删除元素

v-show: 仅仅是元素的显示和隐藏  (仅仅更改display属性)

特点:v-if 有较高的切换性能消耗,v-show有较高的初始渲染消耗。如果元素涉及频繁的切换最好不用v-if,如果元素不怎么显示最好不要用v-show,不然会浪费初始渲染,同等情况下v-if根本就不会渲染。

案例9:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">
    <!-- 点击toggle来比较v-if 和 v-show的效果 -->
    <input type="button" value="toggle" @click="flag=!flag">

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

    <!-- v-if 有较高的切换性能消耗 -->
    <!-- v-show 有较高的初始渲染消耗 -->

    <!-- 如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show -->
    <!-- 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if -->
    <h3 v-if="flag">这是用v-if控制的元素</h3>
    <h3 v-show="flag">这是用v-show控制的元素</h3>

  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
     
    });
  </script>
</body>

</html>