zoukankan      html  css  js  c++  java
  • 横冲直撞vue(第四篇):v-model、指令系统总结、指令系统示例轮播图实现、指令系统示例跑马灯效果实现、在vue中使用样式的方式

     

    一、 v-model

    v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

    尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

    v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件:

    • text 和 textarea 元素使用 value 属性和 input 事件;

    • checkbox 和 radio 使用 checked 属性和 change 事件;

    • select 字段将 value 作为 prop 并将 change 作为事件。

     

    vue的核心:声明式的指令和数据的双向绑定。

    什么是数据的双向绑定?另外,大家一定要知道vue的设计模式:MVVM

    M是Model的简写,V是View的简写,VM就是ViewModel。

    单向绑定和双向绑定的区别?

    单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。

    有单向绑定,就有双向绑定。

    如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

    什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定。

    其实单项数据也有双向绑定的意思,不过页面变动后数据的变化不会发生自动更新。

    可以这样认为:双向数据绑定=单向数据绑定+UI事件监听。

    先看个vue中双向数据绑定的例子:

    <body>
      <div id="app">
        <input type="text" v-model="msg">
        <p>{{msg}}</p>
      </div>
    ​
    ​
    ​
      <script src="./lib/vue.js"></script>
      <script>
        var app = new Vue({
          el:'#app',
          data :{
            msg:''
          }
          
        })
      </script>
    </body>
    

      

     

    页面效果如下

     

     

    效果显示,当我们在input输入框中输入内容的时候,下面p标签同步显示内容。这就是最典型的双向数据绑定的例子。vue里使用v-model实现此想法。

     

    浅析理解v-model实现过程

    <body>
        <div id="app">
            <!-- v-model这个指令很好理解,其实它就是一个语法糖 (甜甜的) 它是oninput事件和绑定value的实现 -->
            <input type="text"  :value = 'text' @input = 'valueChange'>
            <h3>{{ text }}</h3>
    ​
        </div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
    ​
        <script type="text/javascript">
            
            new Vue({
                el:"#app",
                template:``,
                data(){
                    return {
                        text:'hello'
                    }
                },
                methods:{
                    valueChange(event){
                        console.log(event.target.value);
                        this.text = event.target.value  
                    }
                }
            });
        </script>
        
    </body>
    

      

     

    分析:v-mode指令是v-bind:vlaue 和v-on:input的结合体。针对input标签使用v-bind绑定value属性,使得input标签实时接收data的数据驱动,h3标签直接采用模板插值法,由data直接驱动,这是model对view

    的单向绑定。

    针对input标签绑定valuechange,数值变动事件,当input的数值发生变动时,由valueChange函数针对this.text的数值进行处理,这是view对model的单向绑定。由此构成了双向绑定。

    用v-model实现简易计算器

    <body>
      <div id="app">
        <input type="text"  v-model='num1'>
        <select v-model='opt'>
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
    ​
        <input type="text"  v-model='num2'>
        <button value='=' @click='calc'>=</button>
        <input type="text"  v-model='res'>
    ​
      </div>
    ​
      <script src="./lib/vue.js"></script>
      <script>
        var app = new Vue({
          el:'#app',
          data :{
            num1:0,
            num2:0,
            res:0,
            opt:'+'
          },
          methods: {
    ​
                calc(){
    ​
                    var calcStr = 'parseInt(this.num1)'+ this.opt + 'parseInt(this.num2)';
                    this.res = eval(calcStr);
                }
                }
          
        })
      </script>
    </body>
    

      


     

     

    二、指令系统总结

     

    1、注意v-bind和v-on的简写

      v-bind的简便写法,可以直接用 : 替代:

    <img :src="imgSrc" :title="time">    <==对应==>   
    <img v-bind:src="imgSrc" v-bind:title="time">
    

      

      v-on的简便写法,可以直接用 @ 替代:

    <button @click = "clickHandler">切换</button>  <==对应==>  
    <button v-on:click="clickHandler">切换</button>
    

      

     

    2、对页面的dom进行赋值的运算

      v-test、v-html、{{}}都是对页面的dom进行赋值,相当于js中的 innnerText 和 innerHTML。

     

    3、对页面的dom进行条件渲染

    (1)v-if的内在过程

    v-if = 'true':    
    <!--创建-->   
    var oP = document.createElement('p');  
    oDiv.appendChild(op);
    v-if= 'false':   
    <!--销毁-->   
    oDiv.removeChild(op);`
    

      

    (2)v-show的内在过程

    v-show = 'true':  
    oDiv.style.display = 'block';
    ​
    v-show = 'false':   
    oDiv.style.display = 'none'
    

      

    (3)v-bind内在过程

    v-bind:class:
    oDiv.className += ' active'
     
    

      

    4、v-if与v-show的区别

      实现方式区别:v-if是根据后面数据的真假值判断直接从Dom树上删除或重建元素节点;v-show只是在修改元素的css样式,也就是display的属性值,元素始终在Dom树上。

      编译过程区别:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件; v-show只是简单的基于css切换。

      编译条件区别:v-if是惰性的,如果初始条件为假,则什么也不做,只有在条件第一次变为真时才开始局部编译; v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素始终被保留。

      性能消耗区别:v-if有更高的切换消耗,不适合做频繁的切换; v-show有更高的初始渲染消耗,适合做频繁的额切换。

     

    5、vue的思想

      vue是渐进式的JavaScript框架。大多数人觉得做加法比做减法简单。

      vue这个框架将做减法的事情(困难的部分)都帮忙做了,人们只需要简单的部分就能实现复杂的dom操作。

     

     

    三、指令系统之轮播图实现

    1、轮播图简单示例

     

    	<style type="text/css">
    		ul{
    			list-style: none;
    			overflow: hidden;
    			 400px; 
    		}
    		ul li{
    			float: left;
    			 100px;
    			height: 40px;
    			line-height: 40px;
    			background-color: purple;
    			color: #fff;
    			text-align: center;
    		}
    		ul li.active{
    			background-color: green;
    		}
    	</style>
    </head>
    <body>
    	<div id="slider">
    		
    		<img :src='currentImgSrc' alt="">
    		<ul>
    			<li v-for = '(item,index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
    				{{ index +1 }}
    			</li>
    		</ul>
    	</div>
    	<script src="./lib/vue.js"></script>
    	<script type="text/javascript">
    		// 数据驱动视图
    
    		var imgArr = [
    			{id:1,imgSrc:'./images/1.jpg'},
    			{id:2,imgSrc:'./images/2.jpg'},
    			{id:3,imgSrc:'./images/3.jpg'},
    			{id:4,imgSrc:'./images/4.jpg'}
    
    		];
    		new Vue({
    			el:'#slider',
    			template:``,
    			data(){
    				return{
    					imgArr:imgArr,
    					currentIndex:0,
    					currentImgSrc:'./images/1.jpg'
    				}
    			},
    			methods:{
    				clickHandler(index){
    					this.currentIndex = index;
    					this.currentImgSrc = this.imgArr[index].imgSrc;
    				}
    			}
    		});
    	</script>
    	
    </body>
    

      

    页面效果如下

     

    2、轮播图进阶

    (1)增加点击下一张

    	<style type="text/css">
    		ul{
    			list-style: none;
    			overflow: hidden;
    			 400px; 
    		}
    		ul li{
    			float: left;
    			 100px;
    			height: 40px;
    			line-height: 40px;
    			background-color: purple;
    			color: #fff;
    			text-align: center;
    		}
    		ul li.active{
    			background-color: green;
    		}
    	</style>
    </head>
    <body>
    	<div id="slider">
    
    			<img :src='currentImgSrc' alt="">
    			<ul>
    				<li v-for = '(item,index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
    					{{ index +1 }}
    				</li>
    			</ul>
    			<button class="btn" @click='nextImg'>下一张</button>
    			
    
    		
    	</div>
    	<script src="./lib/vue.js"></script>
    	<script type="text/javascript">
    		// 数据驱动视图
    
    		var imgArr = [
    			{id:1,imgSrc:'./images/1.jpg'},
    			{id:2,imgSrc:'./images/2.jpg'},
    			{id:3,imgSrc:'./images/3.jpg'},
    			{id:4,imgSrc:'./images/4.jpg'}
    
    		];
    		new Vue({
    			el:'#slider',
    			template:``,
    			data(){
    				return{
    					imgArr:imgArr,
    					currentIndex:0,
    					currentImgSrc:'./images/1.jpg'
    				}
    			},
    			methods:{
    				clickHandler(index){
    					this.currentIndex = index;
    					this.currentImgSrc = this.imgArr[index].imgSrc;
    				},
    				nextImg(){
    					if(this.currentIndex==this.imgArr.length-1){
    						this.currentIndex = -1;
    					}
    
    					this.currentIndex++;
    					this.currentImgSrc =  this.imgArr[this.currentIndex].imgSrc;
    				}
    
    			}
    		});
    	</script>
    	
    </body>
    

      

    页面显示效果

    (2)实例生命周期钩子

      每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

      比如 created 钩子可以用来在一个实例被创建之后执行代码:

    	<style type="text/css">
    		ul{
    			list-style: none;
    			overflow: hidden;
    			 400px; 
    		}
    		ul li{
    			float: left;
    			 100px;
    			height: 40px;
    			line-height: 40px;
    			background-color: purple;
    			color: #fff;
    			text-align: center;
    		}
    		ul li.active{
    			background-color: green;
    		}
    	</style>
    </head>
    <body>
    	<div id="slider">
    
    			<img :src='currentImgSrc' alt="">
    			<ul>
    				<li v-for = '(item,index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
    					{{ index +1 }}
    				</li>
    			</ul>
    			<button class="btn" @click='nextImg'>下一张</button>
    
    
    		
    	</div>
    	<script src="./lib/vue.js"></script>
    	<script type="text/javascript">
    		// 数据驱动视图
    
    		var imgArr = [
    			{id:1,imgSrc:'./images/1.jpg'},
    			{id:2,imgSrc:'./images/2.jpg'},
    			{id:3,imgSrc:'./images/3.jpg'},
    			{id:4,imgSrc:'./images/4.jpg'}
    
    		];
    		new Vue({
    			el:'#slider',
    			template:``,
    			data(){
    				return{
    					imgArr:imgArr,
    					currentIndex:0,
    					currentImgSrc:'./images/1.jpg'
    				}
    			},
    			created(){
    				 // 生命周期方法
                setInterval(this.nextImg, 2000)  
                // setInterval()方法可按照指定的周期(以毫秒计)来调用函数或计算表达
    			},
    
    			methods:{
    				clickHandler(index){
    					this.currentIndex = index;
    					this.currentImgSrc = this.imgArr[index].imgSrc;
    				},
    				nextImg(){
    					if(this.currentIndex==this.imgArr.length-1){
    						this.currentIndex = -1;
    					}
    
    					this.currentIndex++;
    					this.currentImgSrc =  this.imgArr[this.currentIndex].imgSrc;
    				}
    
    			}
    		});
    	</script>
    	
    </body>
    

      

    设置created生命周期方法后,页面上自动轮播图片

    也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mountedupdateddestroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。

      created方法还可以用来获取cookie和session。

    (3)鼠标 移入/移出 时 停止/开启 定时器

     

    	<style type="text/css">
    		ul{
    			list-style: none;
    			overflow: hidden;
    			 400px; 
    		}
    		ul li{
    			float: left;
    			 100px;
    			height: 40px;
    			line-height: 40px;
    			background-color: purple;
    			color: #fff;
    			text-align: center;
    		}
    		ul li.active{
    			background-color: green;
    		}
    	</style>
    </head>
    <body>
    	<div id="slider">
    
    			<img :src='currentImgSrc' alt="" @mouseover='stoptimer' @mouseleave='opentimer'>
    			<ul>
    				<li v-for = '(item,index) in imgArr' :class="{active:currentIndex==index}" @click='clickHandler(index)'>
    					{{ index +1 }}
    				</li>
    			</ul>
    			<button class="btn" @click='nextImg'>下一张</button>
    
    
    		
    	</div>
    	<script src="./lib/vue.js"></script>
    	<script type="text/javascript">
    		// 数据驱动视图
    
    		var imgArr = [
    			{id:1,imgSrc:'./images/1.jpg'},
    			{id:2,imgSrc:'./images/2.jpg'},
    			{id:3,imgSrc:'./images/3.jpg'},
    			{id:4,imgSrc:'./images/4.jpg'}
    
    		];
    		new Vue({
    			el:'#slider',
    			template:``,
    			data(){
    				return{
    					imgArr:imgArr,
    					currentIndex:0,
    					currentImgSrc:'./images/1.jpg',
    					timer:null
    				}
    			},
    			created(){
    				 // 生命周期方法
                this.timer = setInterval(this.nextImg, 500)  
                // setInterval()方法可按照指定的周期(以毫秒计)来调用函数或计算表达
    			},
    
    			methods:{
    				clickHandler(index){
    					this.currentIndex = index;
    					this.currentImgSrc = this.imgArr[index].imgSrc;
    				},
    				nextImg(){
    					if(this.currentIndex==this.imgArr.length-1){
    						this.currentIndex = -1;
    					}
    
    					this.currentIndex++;
    					this.currentImgSrc =  this.imgArr[this.currentIndex].imgSrc;
    				},
    				stoptimer(){
    					clearInterval(this.timer); //停止定时器
    				},
    				opentimer(){ 
    					 this.timer = setInterval(this.nextImg, 500)  
    					 //开启定时器
    				}
    
    
    			}
    		});
    	</script>
    	
    </body>
    

      

     

    页面显示效果

     

     

     注意开启定时器时不能直接调用this.created生命周期方法,必须直接开启定时器。

     

    四、指令系统之跑马灯效果实现

     

    <body>
      <!-- 2. 创建一个要控制的区域 -->
      <div id="app">
        <input type="button" value="浪起来" @click="lang">
        <input type="button" value="低调" @click="stop">
    
        <h4>{{ msg }}</h4>
    
      </div>
    
      <script>
        // 注意:在 VM实例中,如果想要获取 data 上的数据,或者 想要调用 methods 中的 方法,必须通过 this.数据属性名  或  this.方法名 来进行访问,这里的this,就表示 我们 new 出来的  VM 实例对象
        var vm = new Vue({
          el: '#app',
          data: {
            msg: '猥琐发育,别浪~~!',
            intervalId: null // 在data上定义 定时器Id
          },
          methods: {
            lang() {
              // console.log(this.msg)
              // 获取到头的第一个字符
              // this
    
              if (this.intervalId != null) return;
    
              this.intervalId = setInterval(() => {
                var start = this.msg.substring(0, 1)
                // 获取到 后面的所有字符
                var end = this.msg.substring(1)
                // 重新拼接得到新的字符串,并赋值给 this.msg
                this.msg = end + start
              }, 400)
    
              // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去;【好处:程序员只需要关心数据,不需要考虑如何重新渲染DOM页面】
            },
            stop() { // 停止定时器
              clearInterval(this.intervalId)
              // 每当清除了定时器之后,需要重新把 intervalId 置为 null
              this.intervalId = null;
            }
          }
        })
    
    
        // 分析:
        // 1. 给 【浪起来】 按钮,绑定一个点击事件   v-on   @
        // 2. 在按钮的事件处理函数中,写相关的业务逻辑代码:拿到 msg 字符串,然后 调用 字符串的 substring 来进行字符串的截取操作,把 第一个字符截取出来,放到最后一个位置即可;
        // 3. 为了实现点击下按钮,自动截取的功能,需要把 2 步骤中的代码,放到一个定时器中去;
      </script>
    </body>
    

      

    页面显示效果

    五、在Vue中使用样式(v-bind补充)

    使用class样式

    1. 数组

    <h1 :class="['red', 'thin']">这是一个邪恶的H1</h1>
    

      

    1. 数组中使用三元表达式

    <h1 :class="['red', 'thin', isactive?'active':'']">这是一个邪恶的H1</h1>
    

      

    1. 数组中嵌套对象

    <h1 :class="['red', 'thin', {'active': isactive}]">这是一个邪恶的H1</h1>
    

      

    1. 直接使用对象

    <h1 :class="{red:true, italic:true, active:true, thin:true}">这是一个邪恶的H1</h1>
    

      

    使用内联样式

    1. 直接在元素上通过 :style 的形式,书写样式对象

    <h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>
    

      

    1. 将样式对象,定义到 data 中,并直接引用到 :style

    • 在data上定义样式:

    data: {
            h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
    }
    

      

    • 在元素中,通过属性绑定的形式,将样式对象应用到元素中:

    <h1 :style="h1StyleObj">这是一个善良的H1</h1>
    

      

    1. :style 中通过数组,引用多个 data 上的样式对象

    • 在data上定义样式:

    data: {
            h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
            h1StyleObj2: { fontStyle: 'italic' }
    }
    

      

    • 在元素中,通过属性绑定的形式,将样式对象应用到元素中:

    <h1 :style="[h1StyleObj, h1StyleObj2]">这是一个善良的H1</h1>
    

      

     

     

     

     

     

     

     

    参考资料

    [1]https://www.cnblogs.com/crazymagic/p/9726673.html

    [2]https://www.cnblogs.com/yangk1996/p/10844358.html

  • 相关阅读:
    mysql 开发基础系列7 流程函数与其它函数
    mysql 开发基础系列6 数值与日期函数
    html5 浏览器端数据库
    html5 响应式布局
    css 文本溢出显示省略号
    js 字符串的操作
    js 图片轮播(一)
    css 弹出层-透明层
    js选项卡
    js获取当前时间显示在页面上
  • 原文地址:https://www.cnblogs.com/Nicholas0707/p/12677061.html
Copyright © 2011-2022 走看看