首页 > 技术文章 > vue指令之文本指令,事件指令,属性指令,表单指令,条件指令,循环指令,补充实例成员(计算属性和监听属性)

jiangxianseng 2020-05-09 15:58 原文

一.文本指令

示例:

<body>
<meta charset="UTF-8">
   <title>Title</title>
   <!--若不在vue范围中则不变-->
    <div v-text="num"></div>
    <div id="app">
       <p>{{ num }}</p>
       <!--在vue范围中则num就会被替换成文本-->
       <div v-text="num"></div>
        <!--即使有内容也会被num替换掉,即真实DOM虚拟Dom替换掉了-->
       <div v-text="num">123</div>
       <!--v-text只是单纯的将渲染控制的标签内容进行替换成文本,而v-html可以解析渲染内容的html语法-->
       <div v-text="info">123</div>
       <div v-html="info"></div>
        <!--在内部直接写标签可以用反引号加${}接收变量
        <div v-html="<b>`${info}`</b>"></div>


   </div>
</body>
<script src="vue/vue.js"></script>
<script>
   new Vue({
       el:'#app',
       data:{num:10,
       info:'<i style="color:red">info内容</i>'}
  })
</script>

 

 

 

总结:

1) v-* 是vue指令,会被vue解析,v-text="num"中的num是变量(指令是有限的,不可以自定义)
2)v-text是原样输出渲染内容,渲染控制的标签自身内容会被替换掉(<p v-text="num">123</p>会被num替换)
3)v-html可以解析渲染html语法的内容


4)补充
<!-- js基本数据类型:字符串、数字、布尔、undefined -->
# 直接 <p v-text="abc"表示的abc是变量,而"'abc'"才是字符串
<p v-text="'abc' + num + 10"></p>
<p>{{ 'abc' + num + 10 }}</p>

二.事件指令

<body>
   <div id="app">
  <!-- <button>按钮</button>-->
       
       <button v-on:click="btnClick">{{ btn1 }}</button>

       <button v-on:click="btnClick">{{ btn2 }}</button>
       <hr>

       <!-- 直接绑定事件名:系统会在触发事件时(点击时)调用事件方法(fn1),传给事件方法一个参数(事件对象) -->
       <button v-on:click="fn1">按钮3</button>

       <!-- 绑定的事件名后跟着(),不是主动调用事件方法,而是表示在触发事件调用时,传入的参数全由用户自己决定 $event表示传入系统事件-->
       <button v-on:click="fn2($event, 10, 20)">按钮4</button>

       <hr>
       <button v-on:click="fn(btn1)">{{ btn1 }}</button>

       <button v-on:click="fn(btn2)">{{ btn2 }}</button>
   </div>
</body>
<script src="js/vue.js"></script>
<script>
   // 对比DOM驱动(注意使用Dom驱动需要注释掉Vue环境,要不然会变成数据驱动,DOM会失效):1)js选择器获取目标标签 2)为目标标签绑定事件 3)在事件中完成相应逻辑
   // var btn = document.getElementsByTagName('button')[0];
   // btn.onclick = function () {
   //     console.log(111111111111);
   // };
   new Vue({
       el: '#app',
       data: {
           btn1: '按钮1',
           btn2: '按钮2',
      },
       // 声明一个方法
       methods: {
           btnClick () {
               console.log(666)
          },
           fn1 (ev) { //ev就是event的简写,表示点击点的x和y坐标
              console.log(ev.clientX, ev.clientY);
          },
           fn2(ev, n1, n2) {//若参数数量不够打印出来就是undefind
               console.log(ev, n1, n2);
               console.log(ev.clientX, ev.clientY);
          },
           fn (msg) {
               console.log(msg);
          }
      }
  })
</script>

总结:

一、数据驱动
1)操作是一个功能,使用需要一个方法来控制 2)方法名是变量,所以控制变量就可以控制该方法


二、事件指令
1)在实例成员methods中声明事件方法
2)标签通过事件指令绑定声明的方法: v-on:事件名="事件方法名"
    eg: <button v-on:click="btnClick">按钮</button>
3)标签通过事件指令绑定声明的方法,且自定义传参: v-on:事件名="事件方法名()"
    eg: <button v-on:click="btnClick()">按钮</button>  不传任何参数
    eg: <button v-on:click="btnClick($event)">按钮</button>  传入事件对象,同不写()
    eg: <button v-on:click="btnClick(10)">按钮</button>  只传入自定义参数,当然也可以传入事件对象

三.js对象的补充

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>js对象补充</title>

</head>
<body>

</body>
<script>
// (1)js没有字典类型,只有对象类型,通过对象可以代替字典,var可以声明一个变量
   var dic_obj = {
       // 属性:值(可以是数值或函数)
       'name': 'Bob',
       'eat':function () {
           console.log('在吃饭')
      }
  }

   console.log(dic_obj.name)
   dic_obj.eat()
 // 通过字典索引key一样可以
   console.log(dic_obj['name'])
   // 只要能获取到内存地址一样可以运行函数
   dic_obj['eat']()

// (2)由于js中的属性名都采用字符串类型,所以省略引号
var obj = {
       // 属性:值(数值或函数)
       name : 'Bob',
       eat :function () {
           console.log('在吃饭')
      }
  }

   console.log(obj.name)
   obj.eat()
 // 通过字典索引key一样可以
   console.log(obj['name'])
   // 只要能获取到内存地址一样可以运行函数
   obj['eat']()

// (3)省略引号,属性值为函数时是方法方法也可以简写,去掉:function
var obj = {
       // 属性:值(数值或函数)
       name : 'Bob',
       eat() {
           console.log('在吃饭')
      }
  }

   console.log(obj.name)
   obj.eat()
 // 通过字典索引key一样可以
   console.log(obj['name'])
   // 只要能获取到内存地址一样可以运行函数
   obj['eat']()

// (4)如果对象的属性值是一个变量,且变量名与属性名相同,还可以简写:{属性,}
   var height = 180
   // var a = {
   //     height:heig ht
   // }
   // 并不会写成上面这种形式,而是下面这种简写
   var a = {
       height
  }
   console.log(height)
</script>

</html>
<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="UTF-8">
   <title>对象补充</title>
</head>
<body>

</body>
<script src="js/vue.js"></script>
<script>
// js中的类
   // 第一种声明类的方法,用{}表示作用域
   class People {
       //constructor表示构造
       constructor (name) {
           //this在js的类中就是调用这个类产生的对象,类似于python类中的self
           this.name = name
      }
       // 方法中省去了function,简写了
       eat () {
           console.log(this.name + '在吃饭')
      }
  }
   //let是局部声明变量
   let p1 = new People('Bob');
   let p2 = new People('Tom');
   console.log(p1.name, p2.name);
   p1.eat();

   // 第二种声明类的方法(难点):在函数内部出现了this语法,该函数就是类,否则就是普通函数,并且若是方法名开头是大写也是类(规范写法,不强制)
   function Teacher(name) {
       this.name = name;
       this.eat =function () {
           console.log(this.name + '在吃饭')
      }
  }
   let t1 = new Teacher('Owen');
   t1.eat();

   // 类属性:给类属性赋值,所有对象都能访问
   function Fn() {}
   let f1 = new Fn();
   let f2 = new Fn();

   // 通过prototype赋值类属性,所有的对象都能访问到这个属性
   Fn.prototype.num = 100;

   console.log(f1.num);
   console.log(f2.num);

   // 类似于单例
   //Vue就相当于一个函数,通过源码看到最终返回的是一个vue对象,也是一个函数地址
   Vue.prototype.num = 1000;
   let v1 = new Vue();
   let v2 = new Vue();
   console.log(v1.num);
   console.log(v2.num);
</script>
</html>

四:js函数补充

// 1)函数的形参与调用时传入的实参关系(你传你的,我收我的)
//      传入和接受的参数个数不需要一致
//      但是一定按位进行赋值(没有关键字参数)
//      没有接收的实参会被遗弃,没有被赋值的形参会被赋值为undefined
function fn1(a, b) {
   console.log(a, b);
   return a + b;
}

let res = fn1(10, 20, 30);
console.log(res);

// 2)函数定义的演变
let fn2 = function (a, b) {
   return a + b;
};

// 省略关键字的箭头函数
let fn3 = (a, b) => {
   return a + b;
};

// 没有函数体,只有返回值的函数,可以省略作用域{},由于只有返回值,所以return也省略
let fn4 = (a, b) => a + b;
console.log(fn4(11, 22));

// 如果形参只有一个时,声明参数的()也可以省略
let fn5 = num => num * num;
console.log(fn5(3));

// 弱语言:对数据格式不敏感
console.log(10 + '5');  #105
console.log(10 - '5');  #5
console.log(+'55555'); # 可以将字符串改为数字的形式

 

五.斗篷指令(了解)

"""
v-cloak:避免屏幕闪烁
1)属性选择器,会将v-cloak属性所在的标签隐藏
2)当vue环境加载后,会将v-cloak属性解析移除,所以内容{{ num }}就会显示出来
3)而现在vue已经准备完毕,所以用户会直接看到数值10,而不会看到 页面从{{ num }}闪烁成数值10   """
<style>
  [v-cloak] {
       display: none;
  }
</style>
<div id="app" v-cloak>
   <p>{{ num }}</p>
</div>
<script>
   new Vue({
       el: '#app',
       data: {
           num: 10
      },
  })
</script>

 

六.属性指令

"""
/** 属性指令
* 1)语法:v-bind:属性名="变量"
* 2)针对不同属性,使用方式稍微有一丢丢区别
*     i)自定义属性以及title这些,直接赋值的,使用方式如下(t是变量,'o'是常量)
*         <p v-bind:title="t" v-bind:owen="'o'">段落</p>
*     ii)class属性(重点):
*         绑定的变量:值可以为一个类名 "p1",也可以为多个类名 "p1 p2"
*         绑定的数组:数组的每一个成员都是一个变量
*         绑定的字典:key就是类名,value是绝对该类名是否起作用
*     iii)style属性(了解):
*         绑定的变量:值是一个字典
*/
"""
<p v-bind:title="t" v-bind:owen="'o'">段落</p>
<script>
   new Vue({
       el: '#app',
       data: {
           t: '悬浮提示',
      },
  })
</script>
<!-- 
a是变量,值就是类名
b就是类名,不是变量
c是变量,值为布尔,决定b类是否起作用
d是变量,值可以为一个类名 'p1' 也可以为多个类名 "p1 p2 ..."
calss="p1 b p2 p3"
-->
<p v-bind:class="[a, {b: c}]" v-bind:class="d"></p>
<script>
   let app = new Vue({
       el: '#app',
       data: {
           a: 'p1',
           c: true,
           d: 'p2 p3',
      },
  })
</script>
<p v-bind:style="myStyle"></p>
<script>
   let app = new Vue({
       el: '#app',
       data: {
           myStyle: {
               width: '50px',
               height: '50px',
               backgroundColor: 'pink',
               borderRadius: '50%'
          }
      },
  })
</script>
案例
<button v-bind:class="{live: isLive == 1}" v-on:click="changeLive(1)">1</button>
<button v-bind:class="{live: isLive == 2}" v-on:click="changeLive(2)">2</button>
<button v-bind:class="{live: isLive == 3}" v-on:click="changeLive(3)">3</button>
<script>
   let app = new Vue({
       el: '#app',
       data: {
           isLive: 1,
      },
       methods: {
           changeLive (index) {
               // this就代表当前vue对象,和app变量等价
               // app.isLive = index;
               this.isLive = index;
          }
      }
  })
</script>  

 

重点:事件指令与属性指令都可以简写
<!--
1)v-bind: 可以简写为 :
2)v-on: 可以简写为 @
-->

<button v-bind:class="{live: isLive == 1}" v-on:click="changeLive(1)">1</button>
<button :class="{live: isLive == 2}" @click="changeLive(2)">2</button>
<button :class="{live: isLive == 3}" @click="changeLive(3)">3</button>

 

事件补充

<style>
   body {
       /* 不允许文本选中 */
       user-select: none;
  }
   .d1:hover {
       color: orange;
       /* 鼠标样式 */
       cursor: pointer;
  }
   /* 只有按下采用样式,抬起就没了 */
   .d1:active {
       color: red;
  }
   /* div标签压根不支持 :visited 伪类 */
   .d1:visited {
       color: pink;
  }

   .d2.c1 {
       color: orange;
  }
   .d2.c2 {
       color: red;
  }
   .d2.c3 {
       color: pink;
  }
</style>
<div id="app">
   <div class="d1">伪类操作</div>
   <br><br><br>
   <!--
   click: 单击
   dblclick:双击
   mouseover:悬浮
   mouseout:离开
   mousedown:按下
   mouseup:抬起
   -->
   <div :class="['d2', c]" @click="hFn('c1')" @mouseover="hFn('c2')" @mousedown="hFn('c3')">事件处理</div>
</div>
<script>
   new Vue({
       el: '#app',
       data: {
           c: '',
      },
       methods: {
           hFn (c) {
               this.c = c
          }
      }
  })
</script>

 

八.表单指令

"""
1)语法:v-model="变量"
2)v-model绑定的变量控制的其实就是value属性值
3)v-model要比v-bind:value要对一个监听机制
4)数据的双向绑定:
v-model可以将绑定的变量值映射给表单元素的value
v-model还可以将表单元素的新value映射给报道的变量
"""
<!-- 两个输入框内容会同时变化 -->
<input name="n1" type="text" v-model="v1">
<input name="n2" type="text" v-model="v1">
<script>
   new Vue({
       el: '#app',
       data: {
           v1: ''
      }
  })
</script>

 

九.条件指令

"""
/**
* 1)语法:v-show="变量" | v-if="变量"
* 2)两者的区别:
*     v-show在隐藏标签时,采用display:none渲染标签,标签通过css隐藏
*     v-if在隐藏标签时,不会渲染在页面上
*
* 3)v-if有家族:v-if | v-else-if | v-else
*     v-if是必须的,必须设置条件
*     v-else-if可以为0~n个,必须设置条件
*     v-else可以为0~1个
*     上方分支成立会屏蔽下方所有分支,从上至下依次类推
*/
"""
<div id="app">
   <div>
       <p v-show="isShow">show控制显隐</p>
       <p v-if="isShow">if控制显隐</p>
   </div>

   <div>
       <p v-if="0">你是第1个p</p>
       <p v-else-if="0">你是第2个p</p>
       <p v-else>你是第3个p</p>
   </div>

</div>
<script>
   new Vue({
       el: '#app',
       data: {
           isShow: false,
      }
  })
</script>
案例
<style>
   body {
       margin: 0
  }
   button {
       width: 60px;
       line-height: 40px;
       float: right;
  }
   .bGroup:after {
       display: block;
       content: '';
       clear: both;
  }
   .box {
       /* vw: view width vh: view height*/
       width: 100vw;
       height: 200px;
  }
   .red {
       background-color: red;
  }
   .green {
       background-color: green;
  }
   .blue {
       background-color: blue;
  }

   button.active {
       background-color: cyan;
  }
</style>

<div id="app">
   <div class="bGroup">
       <button :class="{active: isShow === 'red'}" @click="isShow = 'red'">红</button>
       <button :class="{active: isShow === 'green'}" @click="isShow = 'green'">绿</button>
       <button :class="{active: isShow === 'blue'}" @click="isShow = 'blue'">蓝</button>
   </div>
   <div>
       <div v-if="isShow === 'red'" class="box red"></div>
       <div v-else-if="isShow === 'green'" class="box green"></div>
       <div v-else class="box blue"></div>
   </div>
</div>

<script>
   new Vue({
       el: '#app',
       data: {
           isShow: 'red'
      }
  })
</script>

 

十.循环指令

"""
/**
* 1)语法:v-for="ele in obj" obj是被遍历的对象,ele是遍历得到的每一次结果
* 2)遍历可迭代对象的首要结果,都是可迭代对象容器中的值,其次还可以遍历得到索引及键等数据
*     字符串:v-for="v in str" | v-for="(v, i) in str"
*     数组:v-for="v in arr" | v-for="(v, i) in arr"
*     对象:v-for="v in obj" | v-for="(v, k) in obj" | v-for="(v, k, i) in obj"
* 注:v-for遍历要依赖于一个所属标签,该标签及内部所有内容会被遍历复用
*/
"""
<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="UTF-8">
   <title>循环指令</title>
</head>
<body>
   <div id="app">
       <!-- 遍历数字
5
【1】【2】【3】【4】【5】
-->
       <p>{{ d1 }}</p>
       <i v-for="e in d1">【{{ e }}】</i>
       <hr>

       <!-- 遍历字符串
abc
【a】【b】【c】
【0a】【1b】【2c】
-->
       <p>{{ d2 }}</p>
       <i v-for="e in d2">【{{ e }}】</i>
       <i v-for="(e, i) in d2">【{{ i }}{{ e }}】</i>
       <hr>

       <!-- 遍历数组
[ 1, 3, 5 ]
【1】【3】【5】
【01】【13】【25】
-->
       <p>{{ d3 }}</p>
       <i v-for="e in d3">【{{ e }}】</i>
       <i v-for="(e, i) in d3">【{{ i }}{{ e }}】</i>
       <hr>

       <!-- 遍历对象
{ "name": "Bob", "age": 17.5, "gender": "男" }
【Bob】【17.5】【男】
【name-Bob】【age-17.5】【gender-男】
【name-Bob-0】【age-17.5-1】【gender-男-2】
-->
       <p>{{ d4 }}</p>
       <i v-for="e in d4">【{{ e }}】</i>
       <i v-for="(e, k) in d4">【{{ k }}-{{ e }}】</i>
       <i v-for="(e, k, i) in d4">【{{ k }}-{{ e }}-{{ i }}】</i>
       <hr>

   </div>
</body>
<script>
   new Vue({
       el: '#app',
       data: {
           d1: 5,
           d2: 'abc',
           d3: [1, 3, 5],
           d4: {
               name: "Bob",
               age: 17.5,
               gender: "男"
          }
      }
  })
</script>

 

商品循环案例
<style>
   .box {
       width: 280px;
       border: 1px solid #eee;
       border-radius: 5px;
       overflow: hidden; /* 隐藏超出父级显示范围外的内容 */
       text-align: center; /* 文本相关的属性大多默认值是inherit */
       float: left;
       margin: 10px;
  }
   .box img {
       width: 100%;
  }
</style>

<div id="app">
   <div class="box" v-for="obj in goods">
       <img :src="obj.img" alt="">
       <p>{{ obj.title }}</p>
   </div>
</div>

<script>
   let goods = [
      {
           "img": "https://***1.jpg",
           "title": "纯种拆家专家1"
      },
      {
           "img": "https://***2.jpg",
           "title": "纯种拆家专家2"
      },
  ];
   
   new Vue({
       el: '#app',
       data: {
           goods,
      }
  })
</script>

 

面试题:todolist

js的Array操作
"""
尾增:arr.push(ele)  
首增:arr.unshift(ele)
尾删:arr.pop()
首删:arr.shift()
增删改插:arr.splice(begin_index, count, args)
"""
前台数据库
"""
// 存
// 持久化化存储,永远保存
localStorage.name = "Bob";
// 持久化化存储,生命周期同所属标签(页面),页面关闭,重新打开就会丢失
sessionStorage.name = "Tom";

// 取
console.log(localStorage.name);
console.log(sessionStorage.name);

// 清空
localStorage.clear();
sessionStorage.clear();

// 短板:只能存储字符串,所有对象和数组需要转换为json类型字符串,再进行存储
let a = [1, 2, 3];
localStorage.arr = JSON.stringify(a);
let b = JSON.parse(localStorage.arr);
console.log(b);
"""
案例:留言板
<style>
   li:hover {
       color: red;
       cursor: pointer;
  }
</style>

<div id="app">
   <form>
       <input type="text" v-model="info">
       <button type="button" @click="sendInfo">留言</button>
   </form>
   <ul>
       <li v-for="(info, index) in info_arr" @click="deleteInfo(index)">{{ info }}</li>
   </ul>
</div>

<script>
   new Vue({
       el: '#app',
       data: {
           info: '',
           // 三目运算符: 条件 ? 结果1 : 结果2
           info_arr: localStorage.info_arr ? JSON.parse(localStorage.info_arr) : [],
      },
       methods: {
           sendInfo () {
               // 完成留言:将info添加到info_arr
               // 增 push unshift | 删 pop shift
               if (this.info) {
                   // 留言
                   this.info_arr.push(this.info);
                   // 清空输入框
                   this.info = '';
                   // 前台数据持久化(缓存)
                   localStorage.info_arr = JSON.stringify(this.info_arr);
              }
          },
           deleteInfo(index) {
               // 删
               this.info_arr.splice(index, 1);
               // 同步给数据库
               localStorage.info_arr = JSON.stringify(this.info_arr);
          }
      }
  })
</script>

 

字符串补充

"""
1)双引号:
"前缀" + 变量 + "后缀"
<div :title="当前被点击了"+ num + "次"></div>

2)单引号:
'前缀' + 变量 + '后缀'
<div :title="'当前被点击了'+ num + '次'"></div>

3)反引号:
`前缀${变量}后缀`
注:在反引号中可以用 ${} 来包裹变量,实现字符串拼接
<div :title=`当前被点击了+ ${num} + 次`></div>
"""

 

实例成员:计算属性

"""
/** 计算属性:
* 1)其实就是vue中的方法属性,方法名可以作为属性来使用,属性值为方法的返回值
* 2)在computed中声明的方法属性,不能在data中重复声明,比data中声明的属性要多出写逻辑的地方
* 3)方法属性,自带监听机制,在方法属性中出现的变量,都会被监听,一旦有任何被监听的变量值发生更新,
*     方法属性都会被调用更新方法属性的值
* 4)方法属性一定要在页面中渲染一次,方法属性采用意义,多次渲染,方法属性只会被调用一次
* 案例:计算器
* 方法属性的应用场景:一个变量依赖于多个变量,且需要进行一定的逻辑运算
*/
"""
<div id="app">
   <!-- type="number"表示只能写数字 -->
   <input type="number" v-model="num1" max="100" min="0">
  +
   <input type="number" v-model="num2" max="100" min="0">
  =
   <button>{{ sum }}</button>
</div>
<script>
   new Vue({
       el: '#app',
       data: {
           // sum: '', // 重复声明
           num1: '',
           num2: '',
      },
       computed: {
           sum () {
               // num1和num2都在该方法属性中,所以有一个更新值,该方法都会被调用
               if (this.num1 && this.num2) {
                   return +this.num1 + +this.num2;  // +this.num1是将字符串快速转换澄数字
              }
               return '结果';
          }
      }
  })
</script>

 

监听属性

"""
/**
* 1)watch中不定义属性,只是监听属性,所以方法的返回值没有任何意义,只是监听变量值是否发生更新
* 2)watch中的方法名,就是被监听的属性(方法名同被监听属性名)
* 3)被监听的变量值一旦发生更新,监听方法就会被调用
* 应用场景:
*     i)k线图:股票数据变化,页面的k线图重新渲染(需要逻辑将数据转换为图形)
*     ii)拆分姓名:录入姓名,拆分为姓和名(需要逻辑将一个数据拆分为多个数据)
*/
"""
<div id="app">
  姓名:<input type="text" v-model="full_name">
   <hr>
  姓:<button>{{ first_name }}</button>
  名:<button>{{ last_name }}</button>
</div>
<script>
   new Vue({
       el: '#app',
       data: {
           full_name: '',
           first_name: '未知',
           last_name: '未知'
      },
       watch: {
           full_name () {
               if (this.full_name) {
                   // 只是实现简易的拆分逻辑
                   this.first_name = this.full_name.split('')[0];
                   this.last_name = this.full_name.split('')[1];
              } else {
                   this.first_name = '未知';
                   this.last_name = '未知';
              }
          }
      }
  })
</script>

 

 

推荐阅读