Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的渐进式框架。他的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。只关注视图层,它不仅易于上手,还便于与第三方库或项目整合。
在此涉及到的一些知识点后面会解释
首先我们先简单看看如何使用vue
<script src="vue.js文件所在位置">script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<body>
<div id="app">
<h1>{
{message}}h1>
div>
body>
const vm = new Vue({
el:"#app",
data:function(){
return{
//在此定义数据
message:"Hello Vue!",
}
}
});
注:篇幅有点长,但请耐心看完,肯定会有很大的收获!!!
也叫差值表达式用于构造html页面内容。在实际工作中,当同一个模板中想要调用不同的函数来渲染画面,在已经自定义好了的前提下,可以在渲染页面时对传入的参数进行手动判断。
支持变量和表达式
在vue中使用:{ {message}}
message 相当于在js中定义的变量,然后在此语法中进行使用,显示的是对应的值。
mvvm(Model View ViewModel)译为模型、视图、视图模型,其实就是一种软件架构模式。
就是vue事先定义好的,就是对dom元素下命令,拿来用即可
注意:指令都是以 v-** 格式开头
<body>
<div v-**="">div>
body>
v-text
相当于原生js中的innerText属性,将指定的值填充到标签中,会覆盖之前的内容
v-html
相当于原生js中的innerHTML属性,将指定的值填充到标签中,会覆盖之前的内容,可解析标签元素
v-show
根据条件是真或假,来判断元素是否显示,改变的是css样式display:none|block,它只支持布尔值
v-if
根据条件是真或者假,来判断元素是否被渲染,true可以看到这个节点,false该节点不存在,通常与一下两个指令相配合使用(理解成原生js的if…else if…else即可)
v-for
可对一组数据进行迭代输出(可迭代的数据都有下标)
<div id="app">
<h1 v-for="item in datas">{
{item}}h1>
div>
// js代码
<script src="js/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data(){
return{
// 存放一个数组,可根据名字访问值
datas:["数据1","数据2","数据3"],
}
}
})
</script>
<p v-for="(item,index) in list" :key="index">--索引值--{
{i}} --每一项--{
{item}}p>
<p v-for="(user,index) in listObj" :key="index">--id--{
{user.id}} --姓名--{
{user.name}}p>
<p v-for="(val,key,index) in user" :key="index">--键是--{
{key}}--值是--{
{val}}p>
<p v-for="(count,index) in 10" :key="index">这是第{
{count}}次循环p>
<p v-for="(value,index) in str" :key="index">{
{value}}---{
{index}}p>
注意:当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key(即上面代码里的 :key=“index”)
v-on
用于为一个元素绑定事件 可简写为“@”(原生js的所有事件去掉on都可以使用)
格式:v-on:click=”方法名”,
简写:@click=”方法名”,
还有一些常用的修饰符:
.stop 相当于调用event.stopPropagation()
.prevent 相当于调用event.preventDefault()
.self 当子元素身上事件触发后向外扩散,扩散到带有self修饰符的事件不会触发本事件
.once 表示只触发一次此事件的回调
v-bind
用于为元素动态绑定属性 可简写为“:” (绑定的属性它的值是动态变化的)
被绑定的属性它的值支持javascript表达式
格式: v-bind:属性名=”属性值”,
简写: :属性名=”属性值”,
其中在绑定 class 或 style attribute(属性) 时,支持其它类型的值,如数组或对象。
v-model
实现了双向绑定,可以获取表单中输入的value值
注意:只限制在、
常用的修饰符
.lazy 相当于原生js的onchange事件
.number 输入字符串转为有效的数字
.trim 输入首尾空格过滤
v-slot
是一个插槽,可以理解为,可以在引用组件标签中写入内容放在指定的位置。它是为了让我们封装的组件更具有扩展性,决定了组件内部的一些内容到底展示什么。
注意:这在组件(component),中使用,可以先跳过,看完组件在回来看
相当于占位符在组件引用的模板中定义< slot> 标签进行占位,当引用该组件时,在自定义组件标签中添加内容就可以进行填充slot标签
具名插槽,如果想把内容放在指定位置的插槽内,必须在模板中的插槽标签中添加name属性做个标记,然后使用时在需要显示的标签上添加 slot=”name名”
v-pre
表示该元素差值表达式不会进行编译,“{ {}}”这里面的东西不会进行编译,原样输出(直接放入标签中即可,不用给值)
v-cloak
可以使用 v-cloak 指令设置样式,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。
当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码。我们可以使用 v-cloak 指令来解决这一问题。
还可以解决闪烁问题:
当数据量大时未及时渲染会出现闪烁问题,使用属性选择器[v-cloak]{display:none};(直接放入标签中即可,不用给值)
v-once
表示该元素只执行一次,当数据再次渲染值不会改变(直接放入标签中即可,不用给值)
自定义指令有全局和局部之分
首先明白两个概念:
全局指令:写在vue实例外面,每个vue实例挂载元素的范围内都可以使用。
例子:
// xxx这里表示定义的指令名称,就比如 v-model、v-on、v-bind,就是v-**这里定义完使用时必须加前缀"v-**"
Vue.directive('xxx', {
//这里是钩子函数,下面会仔细讲解
inserted: function (el) {
//配置指令
}
});
局部指令:写在vue实例里面,只能指定一个vue实例挂载元素的范围内都可以使用。
var app = new Vue({
el: '#app', //挂载元素
//vue实例里面的所有属性都是固定写法
directives: {
// 与全局指令中的xxx一样,也是表示指令的名字
xxx: {
//添加钩子函数进行配置
}
}
});
扩展———钩子函数
钩子函数是个函数,是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。一段用以处理系统消息的程序。
“钩子”就是在某个阶段给你一个做某些处理的机会。
简单理解,就是不用自己去做,而是有东西帮你做了,就是在相应的时机下帮你处理了一些功能
自定义指令中的钩子函数:
使用格式
//-------全局自定义指令下-------
Vue.directive("test",{
bind:function(){
//逻辑
},
//es6写法
inserted(){
//逻辑
}
});
//-------局部自定义指令下-------
new Vue({
el:"#app",
data(){
return{
}
},
directives:{
//双引号可省略
"test":{
bind:function(){
//逻辑
},
//es6写法
inserted(){
//逻辑
}
}
}
});
函数 | 解析 |
---|---|
bind | 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置 |
inserted | 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 |
update | 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode(虚拟 DOM 的 JavaScript 对象) 更新之前。指令的值可能发生了改变,也可能没有。 |
componentUpdated | 指令所在组件的 VNode 及其子 VNode 全部更新后调用。 |
unbind | 只调用一次,指令与元素解绑时调用。 |
钩子函数中的参数
参数 | 解析 |
---|---|
el | 指令所绑定的元素,可以用来直接操作 DOM。 |
binding | 该参数是一个对象,在下面进行解析该对象中的相关属性 |
vnode | Vue 编译生成的虚拟节点。详解 |
oldVnode | 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。 |
参数binding对象的属性
属性 | 解析 |
---|---|
name | 获取指令名,不包括 v- 前缀。 |
value | 指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2 |
oldValue | 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。 |
expression | 字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。 |
arg | 传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。 |
modifiers | 一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。 |
问题:bind和inserted的区别?
共同点:
dom插入都会调用,bind在inserted之前
不同点:
bind 执行时父节点为 null
inserted 执行时父节点存在。
bind是在dom树绘制前调用,inserted在dom树绘制后调用
简单理解,就是用来存放一些复杂的处理逻辑,一般就是用来通过其他的数据算出一个新数据。
特点:具有缓存能力,当计算属性中引用的值未发生改变时就一直会拿缓存中的数据不会再次执行,提高了运行的速度。
计算属性格式:
new Vue({
el:"#app", //挂载元素,指定该vue对象渲染的范围
data(){
return{
}}, // 定义渲染需要用到的数据
methods:{
}, // 渲染时调用的普通方法
directives:{
}, // 用于设置自定义局部指令
//--------
computed:{
// 使用计算属性,存放复杂逻辑需要计算的方法
// 定义方法
// 注意:方法中必须有return,调用时不加括号
},
})
我理解的计算属性本质:
之所以叫计算属性,其实它本身就是一个属性,调用时不要带“()”,可能到这里有点蒙(是不是想着跟methods中定义的方法一样,确实一样,但是它不是方法就是属性),它的本质就是,一个对象中的属性只不过这个属性有getter和setter方法,一般不会对它进行设置值,只是用来计算获取值,而进行了简写
之所以调用时不用括号的原因也就是这样
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
当你需要在数据变化响应时,执行异步操作,或高性能消耗的操作,那么watch为最佳选择。
(简单理解,就是就是看着一个东西它有没有改变,改变就执行对应的方法,没有就不执行)
侦听器格式
new Vue({
el:"#app", //挂载元素,指定该vue对象渲染的范围
data(){
return{
}}, // 定义渲染需要用到的数据
methods:{
}, // 渲染时调用的普通方法
directives:{
}, // 用于设置自定义局部指令
computed:{
}// 使用计算属性,存放复杂逻辑需要计算的方法
//--------
watch:{
监听的谁:function(newValue,oldValue){
}
// newValue 修改后的内容
//oldValue 修改前的内容
}
})
相关面试题
计算属性中computed的方法和methods中的方法的区别?
- 计算属性中的方法调用时不用加括号,而methods的方法调用时需要加
- 计算属性的每一个计算方法都会被缓存起来,只有当计算属性里面依赖的一个或多个属性变化了,才会重新计算当前计算属性的值。而相反methods中的方法不会缓存。
这个其实很好理解(其实就是例如当一个人进入了一家店,然后换了身衣服出来了,俗话说人衬衣服,马衬鞍,然后出来就变了个样)
过滤器有全局过滤器和局部过滤器之分,常用于格式化文本数据
过滤器可以用在两个地方:
{
{ message | filterName}}
<div v-bind:id="rawId | filterName">div>
全局过滤器
在所有vue对象中挂载的范围内都可以使用
格式:
Vue.filter( filterName,function(msg){
//msg传入的需要过滤的值
return // 数据处理结果 返回出去
});
/*
在模板中使用过滤器时,过滤器会把“|”这个符号前面的值作为第一个参数,传到过滤器中进行相关的操作。
也可指定给过滤器进行传值,例如:
{
{ message | filterName('张三',20)}}
Vue.filter( filterName,function(msg,name,age){
// msg 就是上面这个“|”左边的值
// name,age就是分别对应上面指定传入的值(张三,20)
return msg+ name + age;
});
*/
举例:
<div id="app">
<h3>{
{viewContent | addNamePrefix}}h3>
div>
<script>
Vue.filter("addNamePrefix",(value)=>{
return "my name is" + value
})
let vm = new Vue({
el:"#app",
data(){
return{
viewContent:"张三" ,
}
}
})
</script>
局部过滤器
定义在每个vue实例中,只有在定义过滤器所在的vue对象挂载的范围内可以使用
(其实都差不多,就是位置上有点不一样,功能都是一样的)
举例:
<div id="app">
<p>电脑价格:{
{price | addPriceIcon}}p>
div>
<script>
let vm = new Vue({
el:"#app",
data:{
price:200
},
filters:{
//处理函数
addPriceIcon(value){
console.log(value)//200
return '¥' + value
}
}
})
</script>
其实组件是vue强大功能之一,可以认为它是对html标签进行扩展,可以把相同的代码进行复用。
注意:因为组件是可复用的vue实例所以它们与new Vue实例接收相同的选项(可以认为vue实例自身就是一个组件)
组件也有全局组件和局部组件之分
//格式----
Vue.component("组件名",{
//这里面也可以使用vue实例里面的选项,比如像methods、computed、watch、filters、...
data(){
return{
//要渲染的内容`
}
},
template:"这是一个自定义组件" ,//模板内容
/*
template 可以指定显示的html标签,就是模板用于显示到页面上
*/
});
然后在vue实例挂载的元素中使用<div id=”app”>
<组件名>组件名>
<div>
new Vue({
el:”#app”, //挂载元素,指定该vue对象渲染的范围
data(){
return{
}}, // 定义渲染需要用到的数据
methods:{
}, // 渲染时调用的普通方法
directives:{
}, // 用于设置自定义局部指令
computed:{
},// 使用计算属性,存放复杂逻辑需要计算的方法
watch:{
},//用于监听一个数据的变化
//--------
// 在vue实例中加入
components:{
// 注册组件
//组件名
"组件名":{
// 引用模板(外部使用template标签创建模板)
//可指定选择器,也可在这里直接写
template:"[selector|直接写入]",
//局部组件上面的选项在这里面也可以使用
}
},
})
局部组件使用时与全局组件使用方法一致组件复用
可以将组件进行任意次数的复用
<div id=”app”>
<组件名>组件名>
<组件名>组件名>
<组件名>组件名>
…
<div>
注意事项
a. 组件的模板中的html元素必须有一个元素包裹着
b. 组件中的data必须是一个函数
c. 组件如果是驼峰命名,使用时必须把大写换成-小写
实例
html代码
<div id="app">
<my-div>my-div>
div>
<template id="test">
<div>
<h2>组件模板结构---{
{message}}h2>
<ul>
<li>列表1li>
<li>列表2li>
<li>列表3li>
<li>列表4li>
ul>
<button @click="changeMsg">修改msgbutton>
div>
template>
js代码
<script>
new Vue({
el:"#app", //挂载元素
data(){
//存放渲染需要的数据
return{
}
},
// 注册局部组件
components:{
"my-div":{
// 引用模板
template:"#test",
data(){
return{
message:"hello component"
}
},
methods:{
changeMsg:function(){
this.message = "修改后的msg";
console.log(this);//VueComponent
}
},
},
},
});
</script>
父组件可以使用 props 把数据传给子组件。
步骤
a. 在父组件中引用子组件时,在子组件标签上绑定自定义属性,其属性值是父组件里的data方法中的数据,如 :自定义名=“父组件值”(注:自定义属性名不能有大写字母)
b. 在子组件中通过props接收绑定的属性,如果有多个可用 对象或数组进行存储
// 注册全局组件
Vue.component("hg-son",{
/*
props 可以是数组或对象,用于接收来自父组件的数据。
props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值
*/
// 使用props进行接收
props:["msg","num"], //接收在组件上绑定的属性,数组形式
// 引入模板
template:"#hg"
})
c. 然后在子组件的模板中使用props中的值,即可
附:草图
子组件可以使用 $ emit() 触发父组件的自定义事件。
a. 在子组件中广播数据 使用$emit(“自定义事件”,数据) 创建事件并携带子组件中的数据
b. 然后在引入的子组件标签上绑定此自定义的事件,此事件的值是父组件的方法,该自定义事件所携带的数据可以通过父组件方法中data参数接收
html
<template id="hg">
<div>
<h2>子组件向父组件传递值h2>
<ul>
<li>子组件列表li>
ul>
<button @click="sendParentfn">子组件中的按钮-给父组件传值button>
div>
template>
<div id="app">
<p>接收子组件传递的数据:{
{parentMsg}}p>
<hg-son @toparent="getSonfn">hg-son>
div>
js
<script>
// 注册全局组件
Vue.component("hg-son",{
//引用模板
template:"#hg",
data(){
return{
sonMessage:"msg是子组件中的数据"
}
},
methods:{
sendParentfn(){
console.log(this);
//1. 使用$emit广播数据,toparent是一个自定义事件
// sendParentfn事件被触发后该自定义事件自动触发
this.$emit("toparent",this.sonMessage);
}
}
});
// 创建vue实例
new Vue({
el:"#app",
data(){
return{
parentMsg:"msg是父组件中的数据"
}
},
methods:{
// 自定义事件会将值传入此方法的data中
getSonfn(data){
this.parentMsg = data;
}
}
});
</script>
结合代码,多读几遍步骤,仔细理解
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数。(这里只说下常用的)
使用格式:
new Vue({
el:"#app", //挂载元素,指定该vue对象渲染的范围
data(){
return{
}}, // 定义渲染需要用到的数据
methods:{
}, // 渲染时调用的普通方法
directives:{
}, // 用于设置自定义局部指令
computed:{
}// 使用计算属性,存放复杂逻辑需要计算的方法
watch:{
} // 监听vue实例中数据的变化
//--------
//普通写法
beforeCreate:function(){
//...
},
//ES6写法
beforeCreate(){
//...
},
//...
})
mounted: function () {
this.$nextTick(function () {
//在此处操作
})
}
到这里就结束了,后续还会更新vue全家桶相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!