Vue基础
文章目录
01.初识Vue
MVVM模式(留个坑,学深了再补充)
Vue基础使用
导入Vue.js
let app = new Vue({
el:"#app",
data:{
isLogin : true
},
methods:{
togglePage : function()
{
this.isLogin = !this.isLogin;
}
}
});
ps:上面代码块methods中togglePage若使用箭头函数,this会指向window
02.Vue渲染
条件渲染
v-if : 条件性地渲染一块内容
v-if
v-else
v-else-if(2.1.0新增)作为else if 使用
<body>
<div id="app">
<p>你好,{{username}}</p>
<h3 v-if = "isA" >用户类型:A </h3>
<h3 v-else-if = "isB" >用户类型:B </h3>
<h3 v-else>用户类型:C </h3>
<h3 v-if="Math.random() > 0.5">now you see me</h3>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
username:"小明",
isA:false,
isB:false
}
})
</script>
</body>
v-show
<h1 v-show="ok">Hello!</h1>
v-show不支持元素
ps:
template:用于包裹元素,其本身不会被渲染
一般用于对多个元素同时使用v-if v-for
v-if vs v-show
v-if | v-show | |
---|---|---|
方式 | 删除创建DOM元素 | display样式 |
条件 | 直到为真才会渲染 | 任何条件都会渲染 |
性能 | 更高的切换消耗 | 更高的初始加载消耗 |
场景 | 条件很少改变 | 频繁切换 |
ps:if show 只会添加element.style,假如一开始css中将元素设为display:none 即使if show为true也无法让其显示(即并不会覆盖掉或修改已存在的css属性。)
v-for
<p v-for = "item index in arrs" :key = "index"></p>
v-for 中使用数组
v-for = "item in arr" item->(item,index)
v-for中使用对象
v-for = "value in obj" value -> (value,name,index)
name为属性名
v-for中使用值范围
<div> `
`<span v-for="n in 10">{{ n }} </span> `
`</div>`
列表+条件渲染
使用v-for + v-if
永远不要把 v-if
和 v-for
同时用在同一个元素上。
一般我们在两种常见的情况下会倾向于这样做:
- 为了过滤一个列表中的项目 (比如
v-for="user in users" v-if="user.isActive"
)。在这种情形下,请将users
替换为一个计算属性 (比如activeUsers
),让其返回过滤后的列表。 - 为了避免渲染本应该被隐藏的列表 (比如
v-for="user in users" v-if="shouldShowUsers"
)。这种情形下,请将v-if
移动至容器元素上 (比如ul
、ol
)。
03.模板语法
插值
数据插入内容中:{{}}语法中可以自由使用js表达式
一般插值:数据更改则插值处内容便会更新
用v-once:一次性插值
HTML代码插入内容中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NCbp9xF-1603470796142)(C:\Users\ad_w\AppData\Roaming\Typora\typora-user-images\image-20200506014512893.png)]
指令:带有v-前缀的属性
职责:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
参数
一些指令可以接受参数
1.v-bind指令:响应式更新HTML
<div v-bind:id = "xxx"></div>>
ps🔼:布尔属性值为null、undefined、false 则属性不会出现在渲染出的元素中
2.v-on指令:监听DOM事件
它们的缩写:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ubOxzGIu-1603470796142)(C:\Users\ad_w\AppData\Roaming\Typora\typora-user-images\image-20200506020131189.png)]
动态参数(2.6.0新增):方括号括起来的js表达式
<a v-bind:[attributeName]="url"> ... </a>
这里的 attributeName
会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data
property attributeName
,其值为 "href"
,那么这个绑定将等价于 v-bind:href
。
参数约束
1.动态参数需要字符串,null 用于解除绑定
2.直接在一个 HTML 文件中使用,避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写
3.带有空格或者引号的表达式应使用计算属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTgc4dcI-1603470796143)(C:\Users\ad_w\AppData\Roaming\Typora\typora-user-images\image-20200507220232232.png)]
修饰符
用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
:
04.计算属性和侦听器
计算属性
属性的getter函数
基础使用
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
相较于普通方法
计算属性会基于它们的响应式依赖缓存,相关响应式依赖发生改变时才会再次求值
而普通方法重新渲染时,调用方法总会再次执行函数
相较于侦听属性(watch)
不必对每个属性都添加watch
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
计算属性的setter
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
侦听器
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
05.Class与Style绑定(v-bind)
绑定Class
使用对象
<div v-bind:class = "{error : isError}">11111</div>
<!--bind后不能有空格-->
若isError为true,则会渲染为error class
使用计算属性
<div v-bind:class = "classComputed">222</div>
<!--不需要{}-->>
let app = new Vue({
el:"#app",
data:{
isError:true,
isChose:true
},
methods:{
},
computed:{
classComputed : function(){
return {
error : this.isError && this.isChose ,
choose: this.isChose
}
}
}
});
使用数组
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
数组+对象
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
用在组件上
绑定Style
v-bind:style
与Class绑定类似,注意CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来)
使用对象
使用计算属性
使用数组
多个样式对象绑在一个元素上
多重值
渲染最后一个被浏览器支持的值
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
06.事件处理(v-on)
处理方法
直接写表达式
<button @click = "count++"></button>
方法(可带参数)
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
事件修饰符
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
PS:
<div class="a">
<div class="b"></div>
</div>
a.@click.self.prevent="c"的意思是当你点击的元素是a的时候,才会prevent默认事件,而且执行c事件,如果你点击了b,由于事件冒泡,传播给了a,但是这个时候判断出这个点击事件不是a触发的,所以不会prevent,也不会触发c事件。
a.@click.prevent.self="c"总是先执行prevent,无论是内部元素还是本身元素触发,他都会prevent默认事件。只不过只有当你点击a元素的时候,才会触发c事件,点击内部元素不触发c事件。
按键修饰符
语法:v-on:keyup.xxxx = “”
xxxx:event.key (enter,page-down…)
系统修饰符
.ctrl
.alt
.shift
.meta
<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>
.exact:有且只有
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>
07.表单输入绑定与值绑定
表单输入绑定
基础用法:v-model
通常为字符串,复选框也可以为布尔值
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
-
text 和 textarea 元素使用
value
property 和input
事件; -
checkbox 和 radio 使用
checked
property 和change
事件; -
select 字段将
value
作为 prop 并将change
作为事件。
个人理解:对于checkbox而言 当初始值为数组时,v-model绑定的是value,而初始值为其他类型,v-model绑定的是checked。
值绑定
使用v-bind
<input type="radio" v-model="pick" v-bind:value="a">
选中时有vm.pick === vm.a
复选框可以修改checked
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符:
<input v-model.trim="msg">
08.组件基础
基础使用
1.创建组件构造器const myComponent = Vue.extend({template:"<div></div>"});
(ES6用`可以多行标签 用""则只能单行)
2.注册组件Vue.component("aCom",myComponent);
------------全局组件
3.使用<aCom></aCom>
目前一般无需使用extend,采用语法糖写法:
Vue.component("cpn1",{template:`<div></div>`});
局部组件
let app = new Vue({
el:"#app",
components:{
”aCom“:myComponent
}
});
//<aCom></aCom>只能在app里使用
语法糖:
let cpn = {
template:"#cpn"
}
let app = new Vue({
el:"#app",
components:{
cpn //相当于"cpn":cpn
}
});
父组件与子组件
let myCom1 = Vue.extend({//子组件
template:`
<div>
<h1>myCom1</h1>
<h2>2</h2>
</div>
`
});
let myCom = Vue.extend({ //父组件
template:`
<div>
<h1>myCom</h1>
<h2>1</h2>
<cpn1></cpn1>
</div>
`,
components:{"cpn1":myCom1}//子组件
});
template抽离写法
<script type = "text/x-template" id = "cpn1">
<div></div>
</script>
Vue.component("cpn1",{template:"#cpn1"})
<template id = "cpn1">
</template>
组件中存放数据
Vue.component("cpn1",{
template:"#cpn1",
data(){
return {
counter:0
}
},
methods: {
incre(){
this.counter++;
},
decre(){
this.counter--;
}
},
})
组件中data必须是一个函数,保证每个实例可以维护一份被返回对象的独立的拷贝。(根组件data不是函数)
数据传递父传子
props : 数组/对象 对象可以进行类型限制,默认值和是否必须 一般用对象
类型是数组/对象时,默认值必须为函数
props:["cmess","cCounter","cstu"],
/* 或者
{
cmess: {
type : String,
default: "hi",
},
cCounter:Number,
cstu:Array
},
*/
数据通信子传父——自定义事件
子组件$emit()触发事件,父组件监听子组件事件
<div id="app">
<cpn @cpn-click = "cClick"></cpn>//父监听
</div>
<template id="cpn">
<div >
<button v-for = "item in teams" @click = "cpnClick(item)">{{item.name}}</button>//子触发
</div>
</template>
let cpn = {
template:"#cpn",
data(){
return {}
},
methods:{
cpnClick(item){
this.$emit("cpn-click",item)//触发,与父监听名称对应
}
}
}
let app = new Vue({
el:"#app",
methods: {
cClick(item){ //监听到事件后的事件
console.log(item);
}
},
components:{
cpn
}
});
父子组件直接访问方式
父访问子
1.$children
console.log(this.$children[0].mess);//访问第一个子组件
2.$refs
<cpn2 ref="aaa"></cpn2>
console.log(this.$refs.aaa.mess);
子访问父
访问父组件:$parent
访问根组件:$root
09.插槽slot
基础使用