『前端学习笔记』 Vue.js 基础

本文是Vue.js的基础学习笔记,涵盖了框架与分层架构、Vue实例创建、数据绑定(包括v-bind、v-model)、事件处理(v-on及修饰符)等内容。通过示例介绍了如何在Vue中实现DOM操作的替代方案,如v-text和v-html属性,以及如何利用vue-resource进行Ajax请求。同时,文章还讨论了Vue实例的生命周期和调试工具vue-devtools的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考视频:学 Vue.js 看这个就够了

官方文档:Vue.js





基本概念


框架与分层架构

  • 前端框架
  1. 三大框架ARV:Angular、React、Vue。都比较适合做单页面。

  2. 提高开发效率的发展历程:原生JS - Jquery之类的类库 - 前端模板引擎 - Angular.js / Vue.js

  • Vue.js
  1. Vue.js主要作用:构建用户界面,只关注视图层(MVC)

  2. Vue.js核心概念:不再操作DOM元素,更多关注业务逻辑



  • 框架与库
  1. 框架:完整的解决方案,对项目入侵性较大。如果需要更换框架,则需要重新架构整个项目。

  2. 库(插件):提供某一个小功能,对项目入侵性较小,很容易切换其他库实现需求。


  • MVC与MVVN
  1. MVC:Model模型层,View视图层,Controller控制层。后端分层概念。
  2. MVVM:Model-View-ViewModel,前端视图层概念。

在这里插入图片描述


引入Vue

  • 官方文档
    在这里插入图片描述
  • 引入过程
	<script src="js/vue.js"></script>



绑定数据(innerHTML)



new Vue({ })构造函数

<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', //element元素,实例控制页面上的哪个区域
		data: { //data属性, el中要用到的属性
			msg: 'HelloWorld'
		},
		methods: { //methods方法,el中要用到的方法
			show: ()=>{alert(this.msg)} //this访问
		}
	});
</script>
  • 注意符号
  1. 注意eldatamethods之间的,,和datamethods内部元素之间的,
  2. 注意构造函数内部的{ }
  • 注意事项
  1. el中元素的选择器同CSS
  2. 不可以给body等标签加id


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

data中定义的属性,以插值表达式形式嵌入HTML

  • 基本代码(在body标签内)
<div class="myapp">
	<p>{{msg}}</p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', 
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>

data中自定义的元素msg被写入了p标签。

  • MVVM分析
  1. html中div代码:View视图层
  2. js代码中的vm对象:ViewModel层
  3. js代码中的vm对象中的data:Model层



v-cloak属性(布尔):解决插值表达式闪烁问题

若加载速度较慢,用户可能会先看到{{msg}}这个变量,再看到其对应值。

  • 增加v-cloak属性并设置CSS样式
<style>
	[v-cloak]{
		display: none;
	}
</style>
<div class="myapp">
	<p v-cloak>{{msg}}</p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', 
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>

结果:加载成功之前,调用CSS样式(不显示)



v-text属性:引入文本

  • 渲染数据的两种方式(等效)
<div class="myapp">
	<p v-cloak>{{msg}}</p>
	<p v-text="msg"></p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>
  • 比较
区别插值表达式{{ }}v-text
作用渲染文本数据渲染文本数据
闪烁有闪烁问题闪烁问题
文本任意添加和使用文本覆盖innerHTML



v-html属性:引入文本(含html元素)

<div class="myapp">
	<p v-html="myhtml"></p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data: { 
			myhtml: '<h1>标题</h1>'
		}
	});
</script>



绑定数据


v-bind绑定(缩写:)

将字符串解析为Vue内部数据。

<div class="myapp">
	<!--渲染结果:msg-->
	<input type="button" value="按钮" title="msg"> 
	<!--渲染结果:HelloWorld--> <!--识别为变量-->
	<input type="button" value="按钮" v-bind:title="msg">
	<!--渲染结果:HelloWorld123--> <!--识别为变量:可以使用JS表达式-->
	<input type="button" value="按钮" v-bind:title="msg + '123'">	
	<!--渲染结果:HelloWorld123--> <!--缩写:只保留冒号-->
	<input type="button" value="按钮" :title="msg + '123'">	
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>



绑定CSS:普通样式

包括内部和外部引入。

<style>
	.red{color: red} /*颜色*/
	.thin{font-weight: 200} /*宽度*/
	.italic{font-style: italic} /*斜体*/
	.active{letter-spacing: 0.5em} /*字符间距*/
</style>
<div class="myapp">
	<h1 class="red active">h1</h1> <!--不使用v-bind-->
	
	<h1 :class="['red', 'active']">h1</h1> <!--字符串数组-->
	
	<h1 :class="['red', flag?'active':'']">h1</h1> <!--字符串数组:变量+三元运算符-->
	<h1 :class="['red', {active:flag}]">h1</h1> <!--字符串数组:变量+对象 (对象中可以去掉引号)-->
	
	<h1 :class="[{red:true, active:flag}]">h1</h1> <!--直接使用对象-->
	<h1 :class="classObj">h1</h1> <!--直接使用对象+变量-->
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data:{
			flag: true,
			classObj: {red:true, active:true}
		}
	});
</script>



绑定CSS:内联样式

<div class="myapp">
	<h1 style="color: red">h1</h1> <!--不使用v-bind-->

	<h1 :style="{color: 'red', 'font-weight': 20}">h1</h1> <!--使用对象(必须引号:取值为字符串 属性名带横线)-->
	<h1 :style="styleObj">h1</h1> <!--使用对象:用变量定义-->

  	<h1 :style="[styleObj, styleObj2]">h1</h1> <!--使用对象[数组]:用变量定义-->
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data:{
			flag: true,
			classObj: {red:true, active:true}, //样式集合为类
      		styleObj: {color: 'red', 'font-weight': 20}, //普通样式
      		styleObj2: {'font-style': 'italic'} //普通样式
		}
	});
</script>



v-model属性:双向数据绑定

  • 单向绑定:使用v-bind
<div class="myapp">
	<input type="text" :value="msg">
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', 
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>
  1. 修改msg,页面中的msg被修改
    HTML修改前:
    在这里插入图片描述
    修改msg-使用Chrome的console输入:
    在这里插入图片描述
    HTML修改后:
    在这里插入图片描述

  2. 修改页面中的msg(通过表单input等),msg属性不会被修改。
    HTML修改前:
    在这里插入图片描述
    修改表单文本:
    在这里插入图片描述
    Vue属性修改后:不变
    在这里插入图片描述

  3. 结论
    v-bind只能实现单向数据绑定(ModelView),但无法实现反向数据绑定。


  • 双向绑定:使用v-model属性
<div class="myapp">
	<input type="text" v-model="msg">
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', 
		data: { 
			msg: 'HelloWorld'
		}
	});
</script>

可以解决如上问题。

双向绑定: (ModelView),(ViewModel)

注意:v-model只能运用在表单元素中,基于value属性


  • 使用双向绑定自制简易计算器(略)
  1. 下拉选择框,select标签内有多个option标签。select标签内value属性对应取值。
  2. eval()函数解析字符串并执行,返回执行结果。



绑定事件方法:v-on绑定(缩写@)

<div class="myapp">
	<input type="button" value="按钮" v-on:click="show1"> 
	<input type="button" value="按钮" @click="show1">  
	<input type="button" value="按钮" v-on:click="show2('world')"> 
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data: { 
			msg: 'HelloWorld'
		},
		methods: { 
			show1: ()=>{alert('hello')},
			show2: str=>{alert(str)}
		}
	});
</script>



Vue对象的函数写法

  • 普通定义函数
  1. JS
	function fn1(val){ //普通写法
		return val + 1;
	}
	var fn2 = function(val) { //使用变量承接
		return val + 1;
	}
	const fn3 = function(val) { //使用ES6的const或let
		return val + 1;
	}
  1. JS对象/Vue对象
var vm = new Vue({
		el:'.myapp', 
		methods: { 
			fn: function(val) { //普通函数写法
				return val + 1;
			}
		}
	});

  • ES6箭头函数:this指向上下文相同
  1. JS
	const fn = val => val + 1;
  1. JS对象/Vue对象
var vm = new Vue({
		el:'.myapp', 
		methods: { 
			fn: val => val + 1 //箭头函数
		}
	});

  • ES6名称定义函数
  1. JS
    class中的getset
  2. JS对象/Vue对象
	var vm = new Vue({
		el:'.myapp', 
		methods: { 
			fn(val) {
				return val + 1;
			}
		}
	});



实例:跑马灯效果

  • 原生JS实现
<div>
	<button onclick="openAct()">开启</button>
	<button onclick="closeAct()">关闭</button>
	<p id="mytext">HelloWorld</p>
</div>
<script>
	/*需改变元素的DOM*/
	const mytextDOM = document.getElementById("mytext");
	
	/*轮转字符串函数*/
	const transStr = str => str[str.length - 1] + str.slice(0, str.length - 1); 

	/*开启与关闭*/
	let t;
	const openAct = () => {
		t = setInterval( () => {
			mytextDOM.innerHTML = transStr(mytextDOM.innerHTML);
		}, 500);
	};
	const closeAct = () => {
		clearInterval(t);
	};
</script>
  1. 代码结果:点击开启时,字符串开始旋转
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 代码结果:点击关闭时,字符串停止旋转

  • Vue.js实现
<div class="myapp">
	<button @click="openAct">开启</button>
	<button @click="closeAct">关闭</button>
	<p v-text="msg"></p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp', 
		data: { 
			msg: 'HelloWorld', //字符串
			timer: null //用于接收定时器的变量
		},
		methods: { 
			transStr: 
				str => str[str.length - 1] + str.slice(0, str.length - 1), //字符串单次轮转函数
			openAct(){
				if(this.timer == null){ //debug:多次点击开启会一直分配新的内存空间
					this.timer = setInterval(()=>{ //设置定时器
						this.msg = this.transStr(this.msg); //将字符串轮转单次
					}, 500) //定时器this指向window,应使用箭头函数同质化this或bind()方法绑回this
				}
				
			},
			closeAct(){
				clearInterval(this.timer); //清除定时器
				this.timer = null; //debug:关闭后重新开启
			}
		}
	});
</script>
  1. 使用方法
    使用了v-on绑定点击事件,使用Vue对象中的数据和方法。
  2. 自动监听
    Vue对象会自动监听data中的值会自动同步到页面中。
  3. 优点
    不必操作DOM,不必关心页面渲染,把核心工作放到数据处理。


事件修饰符

  • 总结
事件修饰符作用场景举例
.stop阻止冒泡大标签内小标签,点击时触发两个事件
.prevent阻止默认行为a标签的默认跳转
.capture添加事件监听器时使用捕获模式大标签内小标签,点击时触发两个事件
.self只当事件在该元素(比如不是子元素)本身触发时回调大标签内小标签,点击时触发两个事件
.once事件只触发一次任何事件

  • .stop:阻止冒泡
  1. 普通状态:冒泡
<div class="myapp" @click="fn1">
	<button @click="fn2">按钮</button>
</div>
  1. 使用.stop:阻止冒泡
<div class="myapp" @click="fn1">
	<button @click.stop="fn2">按钮</button>
</div>

建议在子级元素定义。


  • .prevent:阻止默认行为/事件
  1. 普通状态:默认跳转
<div class="myapp">
	<a href="http://www.baidu.com">链接</a>
</div>
  1. 使用.prevent:阻止默认跳转
<div class="myapp">
	<a href="http://www.baidu.com" @click.prevent="fn">链接</a>
</div>

  • .capture:添加事件监听器时使用捕获模式
    冒泡:从内往外
    捕获:从外往内
  1. 普通状态:冒泡从内往外
<div class="myapp" @click="fn1">
	<button @click="fn2">按钮</button>
</div>
  1. 使用.capture:捕获从外往内
<div class="myapp" @click.capture="fn1">
	<button @click="fn2">按钮</button>
</div>

建议在父级元素定义。

  • .self:只当事件在该元素(比如不是子元素)本身触发时回调:添加事件监听器时使用捕获模式
  1. 普通状态:点击内部时,外部会冒泡
<div class="myapp" @click="fn1">
	<button @click="fn2">按钮</button>
</div>
  1. 使用.self:点击内部触发内部,点击外部触发外部
<div class="myapp" @click.self="fn1">
	<button @click="fn2">按钮</button>
</div>

建议在父级元素定义。

.self.stop的区别:.self使自身不会被其它元素向外冒泡,.stop是自身不会触发向外冒泡。

  • .once:事件只触发一次
  1. 普通状态:触发事件
<div class="myapp">
	<a @click="fn">链接</a>
</div>
  1. 使用.once:多次点击只触发一次事件
<div class="myapp">
	<a @click.once="fn">链接</a>
</div>
  1. 可串联特性:可以串联使用事件修饰符
<div class="myapp">
	<a href="http://www.baidu.com" @click.prevent.once="fn">链接</a>
</div>

第一次点击,不跳转(阻止了默认行为),触发事件。
第二次点击,跳转(阻止默认行为只触发一次)。
两者顺序交换,效果等价。



按键修饰符

<div class="myapp">
  <!--键盘事件-->
  <input type="text" onkeyup="alert('键盘事件')"> <!--松开时-->
  <input type="text" onkeydown="alert('键盘事件')"> <!--按下时-->
  <input type="text" onkeypress="alert('键盘事件')"> <!--按下并松开时-->
  <!--使用v-on-->
  <input type="text" @keyup="show">
  <!--按键修饰符-->
  <input type="text" @keyup.enter="show"> <!--按下enter时才触发-->
  <input type="text" @keyup.13="show"> <!--enter的键盘码为13-->
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
    	methods:{
	    	show(){
        	alert("键盘事件")
            }
        } 
	});
</script>

自定义按键修饰符:Vue.config.keyCodes.名称

  • 根据按键码自定义按键修饰符
	Vue.config.keyCodes.myf = 113; 

113F2
如此定义后,可以使用自定义修饰符.myf代表F2。



逻辑渲染


v-for属性:迭代渲染

  • 目标可以为:数组、对象、数字
<div class="myapp">
  <p>普通数组</p>
  <p v-text="mylist"></p>

  <p>迭代数组:参数(, 索引)</p>
  <p v-for="item in mylist">{{item}}</p>
  <p v-for="(myval, myindex) in mylist">The {{myindex}} is {{myval}}</p>

  <p>迭代对象数组</p>
  <p v-for="item in myobjlist">The id {{item.id}} is {{item.name}}</p>

  <p>迭代对象:参数(, 键值, 索引)</p>
  <p v-for="(myval, mykey, myindex) in myobj">The {{myindex}}: {{mykey}} is {{myval}}</p>

  <p>迭代数字:从1到n,而非0到n-1</p>
  <p v-for="i in 5">{{i}}</p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data:{
     		mylist: ['a', 'b'], //数组
      		myobjlist: [{id:1, name:"s1"}, {id:2, name:"s2"}], //数组,每个元素是对象
      		myobj: {id:3, name:"s3"} //对象
		}
	});
</script>
  • 代码结果(检查):
    在这里插入图片描述
    在这里插入图片描述
  • 注意事项
    2.2.0版本后,v-for遍历对象必须有key(HTML)属性
  1. key属性不接受对象,只接收stringnumber
  2. key属性可以用v-bind指定其取值,可以使用v-for中用于遍历的变量(此处为item)中的字符串或数字。
  3. 如果有复选框等,指定key属性可以防止已选定按钮,在(从上往下)添加后会错位的问题。
  4. 结论:key属性将遍历后的结果一一标记。
<div class="myapp">
  <p v-for="item in myobjlist" :key="item.id" style="color:#ff0000">
    <input type="checkbox">
    {{item.id}}: {{item.name}}
  </p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data:{
      		myobjlist: [{id:1, name:"s1"}, {id:2, name:"s2"}] //数组,每个元素是对象
		}
	});
</script>


v-if/v-show属性:选择渲染

<div class="myapp">
  <button @click="trans">切换方式1</button>
  <button @click="flag=!flag">切换方式2</button>
  
  <p v-if="flag">内容</p>
  <p v-show="flag">内容</p>
</div>
<script src="js/vue.js"></script>
<script>
	var vm = new Vue({
		el:'.myapp',
		data:{
     		flag: true
		},
    methods:{
		  trans () { //使用箭头函数this会指向window
		    this.flag = !this.flag;
		  }
    }
	});
</script>
  • 代码结果:取值为true时渲染
  • 比较
条件渲染属性truefalse性能消耗较高的场景
v-if渲染删除渲染后频繁切换布尔值
v-show渲染style="display: none;"初始渲染,尤其是一开始为false且不会改变布尔值



Vue实例的生命周期


生命周期图示

  • 官方文档
    在这里插入图片描述



构造函数对象的生命周期函数 & 构造函数对象总结

<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    /*基础-Vue实例(元素、数据与方法)*/
    el:'.myapp',
    data:{msg:'ok'},
    methods:{},
    /*可复用性&组合-过滤器、自定义指令*/
    filters:{},
    directives: {},
    /*基础-Vue实例-生命周期钩子函数:组件创建*/
    beforeCreate(){},//执行:实例创建之前 //不可用data、methods
    created(){},//执行:实例创建之后 //可用data、methods
    beforeMount(){},//执行:HTML模板已编译,挂载渲染到页面之前 //不可用{{插值表达式}}、DOM
    mounted(){},//执行:HTML模板已编译,挂载渲染到页面之后 //可用{{插值表达式}}、DOM
    /*基础-Vue实例-生命周期钩子函数:组件运行、销毁*/
    beforeUpdate(){},//执行:data数据改变后,HTML界面更新之前
    updated(){},//执行:data数据改变后,HTML界面更新之后
    beforeDestroy(){},//执行:关闭页面,销毁之前 //可用所有Vue内容
    destroyed(){}//执行:关闭页面,销毁之后 //不可用所有Vue内容
  });
</script>

调试工具vue-devtools

参考文档:Vue调试神器vue-devtools安装

安装过程

  1. 获取工具(Github、翻墙、百度等)
  2. 打开Chrome浏览器,最右侧扩展栏点击->更多工具->扩展程序->开发者模式->加载已解压的扩展程序
  3. 将先前获取的工具文件夹添加进去
  4. 在已出现的vuedevtools下,设置详细信息

调试

  • 双向绑定:即时更新
    在这里插入图片描述


vue-resource

Vue 要实现异步加载需要使用到 vue-resource 库。

Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。



引入

<script src="js/vue.js"></script>
<script src="js/vue-resource.js"></script>

vue-resource.js依赖vue.js,要在其之后引入。
就和bootstrap.js依赖jQuery库一样。

引入后可以使用this.$http



跨域问题

参考文档:Chrome - 开发时暂时关闭跨域限制


发起请求

  • Github:示例
    在这里插入图片描述
  • 测试
<div class="myapp">
  <button @click="getInfo">按钮</button>
</div>
<script src="js/vue.js"></script>
<script src="js/vue-resource.js"></script>
<script>
  var vm = new Vue({
    el:'.myapp',
    data:{
      url: 'https://www.baidu.com',
      mydata: {foo: 'bar'}
    },
    methods:{
      getInfo(){
        this.$http.get(this.url).then(
          res => { //successCallback
            console.log(res)
        }, response => { //errorCallback(alternative)
        });
      },
      postInfo(){
        this.$http.get(this.url, this.data).then(
          res => { //successCallback
            console.log(res)
          }, response => { //errorCallback(alternative)
          });
      }
    }
  });
</script>
  • 代码结果
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大熊软糖M

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值