Vue基础篇(二)
本文最后更新于 2024-10-18,文章内容距离上一次更新已经过去了很久啦,可能已经过时了,请谨慎参考喵。
title: Vue基础篇(二)
tags:
- Vue
categories:
- 前端
top_img: false
cover: '/upload/cdn0files/20200724163921.jpg'
abbrlink: 70eafe5c
date: 2020-07-23 14:02:13
updated: 2020-07-23 15:02:13
模板语法
插值表达式
利用插值表达式来输出信息:
<div id="app">
<h1>
{{msg}}
</h1>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
msg:"hello Vue",
},
})
</script>
v-once
属性:
<h1 v-once>{{msg}}</h1>
v-once
是只渲染生成一次,此时如果在控制台更改 app.msg
的值则它并不会改变
插值表达式还支持简单运算:
字符串拼接:
<h1>{{firstname + lastname}}</h1>
运算:
<h1>{{1 + 2}}</h1>
输出结果就是 3 而不是 1 + 2
还支持三元运算:
<div>{{isVip?"VIP用户":"普通用户"}}</div>
若 isVip
为 true
则显示 VIP用户,反之则显示 普通用户
v-html
v-html
也可以用来输出信息,但是这么做并不推荐,因为不是怎么安全,可能会引发 XSS 问题。
<div id="app">
<div>{{htmlTxt}}</div>
<div v-html="htmlTxt"></div>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
htmlTxt:"<h1>hello</h1>"
},
})
</script>
v-bind 属性绑定
v-bind
是动态属性绑定,可以简写为一个冒号 :
<div id="app">
<div v-bind:id="idName"></div>
<div :id="idName"></div>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
idName: "test"
},
})
</script>
这样就可以对属性就行修改。
v-on 事件绑定
v-on
是事件绑定,可以绑定监听事件,也可简写为 @
<div id="app">
<button type="button" v-on:click="changeBg">改变背景</button>
<button type="button" @click="changeBg">改变背景</button>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
methods: {
changeBg () {
document.body.style.background = "skyblue";
}
}
})
</script>
举个小例子,按钮每被点击一次,显示的数字就 +1 :
<div id="app">
<h1>点击次数:{{count}}</h1>
<button type="button" @click="count+=1">点击</button>
<button type="button" @click="clickEvent">点击</button>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
count: 0
},
methods:{
clickEvent () {
this.count++;
}
}
})
</script>
属性内可以使用简单表达式,所有两个按钮都可以修改 count
的数据
v-model 输入绑定
<div id="app">
<input type="text" v-model="userName" />
<input type="text" @input="userName = $event.target.value" :value="userName" />
<h3>输入的内容: {{userName}}</h3>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
userName:"",
},
})
</script>
这两种方法都可以获取到输入框内的值,只不过被简化成了 v-model
指令了。
v-if 判断
例如:
<div id="app">
<img src="" v-if="isShow" />
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
isShow: true
},
})
</script>
如果把 isShow
的值修改为 false
那么图片就不会显示。
v-for 列表渲染
循环渲染一个列表
<div id="app">
<ul>
<li v-for="item in stars">
{{item}}
</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
stars: ["蔡徐坤", "范冰冰", "李晨", "苏有朋"]
}
})
</script>
这就是一个简单的循环列表,但是这么做是不合理的,Vue 的建议是给列表的每一项加上独一无二的 key
值,循环对象数组:
<div id="app">
<ul>
<li v-for="(item,index) in students" :key="index">
<h4>学生姓名:{{item.name}}</h4>
<p>年龄:{{item.age}}------学校:{{item.school}}</p>
</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
students: [{
name: "小明",
age: 18,
school: "北大",
touxiang: "http://pic1.zhimg.com/50/v2-deff985cfcb7690bc71fdf8676438146_hd.jpg"
}, {
name: "小红",
age: 17,
school: "清华"
}, {
name: "小白",
age: 20,
school: "北大"
}]
}
})
</script>
还是上面那个对象数组,进行循环对象:
<ul>
<li v-for="(item,index) in students[0]" :key="index">{{item}}</li>
</ul>
条件循环渲染:
<ul>
<li v-for="(item,index) in students" v-if="item.age%2==0" :key="index">
<h4>索引值:{{index}}------学生姓名:{{item.name}}</h4>
<p>年龄:{{item.age}}------学校:{{item.school}}</p>
</li>
</ul>
这里是先循环再进行判断,即使把
v-if
写在前面也是先循环再判断
常用的指令就这几个,更多和详细指令请参考官方文档:Vue 官方文档
侦听属性
示例:
<div id="app">
{{msg}}
<ul>
<li v-for="(item,index) in arr" :key="index">{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
msg:"hello Vue",
arr:["小红","小黑","小白"]
},
watch:{
msg (val) {
console.log("监听事件被触发---msg");
console.log(val);
},
arr (val) {
console.log("监听事件---arr");
console.log(val);
this.msg="监听到用户数据被修改"
}
}
})
</script>
当 arr
这个数组的值被修改时,比如增加一条数据时,监听事件 arr
被触发,然后这个事件修改了 this.msg
的值,然后也就触发了监听事件 msg
计算属性
<div id="app">
<h1>{{firstname+lastname}}</h1>
<h1>{{fullname}}</h1>
<!-- 逆序显示一个单词 -->
<h1>{{ word.split("").reverse().join("") }}</h1>
<!-- 性能优化。和上面那个例子类似 -->
<h1>{{reverseWord}}</h1>
<!-- 循环性能优化 -->
<ul>
<li v-for="(item,index) in oddStudents" :key="index">
<h2>{{item.name}}</h2>
<h2>{{item.age}}---{{item.school}}</h2>
</li>
</ul>
<!-- set和get属性 -->
<h1>{{msg}}</h1>
<h1>{{reverseMsg}}</h1>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstname:"张",
lastname:"三",
word:"music",
students: [{
name: "小明",
age: 18,
school: "北大"
}, {
name: "小红",
age: 17,
school: "清华"
}],
msg:"hello Vue"
},
computed:{
fullname () {
// 会将计算结果进行缓存
return this.firstname+this.lastname;
},
reverseWord () {
return this.word.split("").reverse().join("");
},
oddStudents () {
let results = this.students.filter((item,i)=>{
return item.age%2==0
});
return results;
},
reverseMsg:{
get () {
return this.msg.split("").reverse().join("");
},
set (val) {
console.log(val);
this.msg = val.split("").reverse().join("");
},
// get只能取值然后作用在其他地方,但是set可以设置值本身
}
},
})
</script>
那么在例子中 {{firstname+lastname}}
和 {{fullname}}
有什么区别呢,因为在计算属性中,只要计算一次,就会将计算结果进行缓存,所以当这个数据需要大量显示的时候,我们可以使用计算属性来提高性能,就不用每显示一次就要进行计算一次。
循环优化的原理:在前面的例子中我们有一个条件循环偶数年龄的学生,我们先进行计算得出偶数学生的数组,就不用循环之后再进行判断,直接把偶数的对象先计算出来再使用,只循环需要的,而且它最大的优点就是可以先把计算结果先缓存下来,只要内容不改变他就可以直接拿来用,从而提高性能
事件传参
<div id="app">
<ul>
<li v-for="(item,index) in stars" @click="clickEvent(index,item,$event)" :key="index">索引值:{{index}}------内容:{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
stars: ["蔡徐坤", "范冰冰", "李晨", "苏有朋"],
},
methods:{
clickEvent (index,value,$event) {
console.log(index);
console.log(value);
console.log(event);
}
},
})
</script>
既能传入事件对象也能传入参数
事件修饰符
<div @click="one">
<button type="button" @click.stop="two">点击</button>
</div>
事件修饰符 .stop
用来阻止冒泡事件,如果没有加修饰符的话,当点击事件 two
被触发时,事件 one
也会被触发,加上修饰符之后就不会了
<form method="post">
<input type="submit" value="提交1"/>
<input @click.prevent="" type="submit" value="提交2"/>
</form>
默认情况下点击 提交1 会有一个 POST 请求被提交,通过 .pervent
修饰符阻止默认行为
<button type="button" @click.once="">只触发一次点击</button>
.once
修饰符是只触发一次,第二次点击就没有效果了
<input type="text" @keydown.enter="search" value="回车" />
keydown
是按键绑定,监听键盘按键的动作
<input type="text" @keydown.enter.f1="search" value="回车和F1" />
同时绑定两个按键
<button type="button" @click.ctrl="ctrlEvent">按住Ctrl事件</button>
按住 Ctrl
键再点击按钮才会触发事件,但是如果按住 Ctrl
和其他键也会触发,就需要精确的只识别 Ctrl
键:
<button type="button" @click.ctrl.exact="ctrlEvent">按住Ctrl事件</button>
<script type="text/javascript">
Vue.config.keyCodes.f1 = 112
var app = new Vue({
el:"#app",
data:{
},
})
</script>
自定义按键修饰符
Class 与 Style 样式绑定
<style type="text/css">
.active {
background: skyblue;
}
.page {
height: 200px;
width: 200px;
}
</style>
<div id="app">
<div class="page" :class="{active:isTrue}"></div>
<!-- 通过对象的方式决定是否存在某个类 -->
<!-- 还可以直接放置对象: -->
<div class="page" :class="styleObj"></div>
<!-- 还可以直接放置数组 -->
<div class="page" :class="styleArr"></div>
<!-- 还可以放置字符串 -->
<div class="page" :class="styleStr"></div>
<!-- 数组和对象混合使用 -->
<div class="page" :class="styleArrObj"></div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
isTrue:true,
styleObj:{active:true,test:true,"col-g-6":true},//可以写多个
styleArr:["col-xs-12","red-bg"],
styleStr:"abc cde efj",
styleArrObj:["abc",{active:true}]
}
})
</script>
内联样式
<div id="app">
<!-- CSS内联样式变量拼接 -->
<div style="width: 100px;height: 100px;background-color: skyblue;"
:style="{border: borderWidth+'px solid red',padding:paddingWidth+'px'}"></div>
<!-- CSS内联样式放置对象 -->
<div :style="styleObj"></div>
<!-- CSS数组的方式拼接 -->
<div :style="styleSrr"></div>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
borderWidth:10,
paddingWidth:30,
styleObj:{
width:"200px",
height:"300px",
"background-color":"skyblue"
},
styleSrr:[
{
width:"200px",
height:"300px",
"background-color":"skyblue"
},{
border:"5px solid yellow"
}
]
}
})
</script>
动态组件
<div id="app">
<div>
<component :is="com"></component>
</div>
<button @click="chooseContent(1)">首页</button>
<button @click="chooseContent(2)">列表</button>
<button @click="chooseContent(3)">新闻</button>
<button @click="chooseContent(4)">个人</button>
</div>
<script type="text/javascript">
// 创建组件
let com1 = Vue.component('index-com',{
name:'index', // 可以给组件定义名字,在is的值上使用
template:`<h1>首页内容</h1>`
})
let com2 = Vue.component('list-com',{
template:`<h1>列表内容</h1>`
})
let com3 = Vue.component('new-com',{
template:`<h1>新闻内容</h1>`
})
let com4 = Vue.component('me-com',{
template:`<h1>个人内容</h1>`
})
var app = new Vue({
el:"#app",
data:{
com:com1,
},
methods:{
chooseContent (id) { // 通过获取id来选择注册的组件
this.com = this.$options.components['com'+id]
}
},
// 注册组件
components:{
com1,com2,com3,com4
}
})
</script>
组件传值
<div id="app">
<ul>
<!-- 从父组件传值到子组件 -->
<product-com @choosproduct="chooseEvent" v-for="(item,index) in proList" :product="item" :key="'product'+index"></product-com>
</ul>
<h1>选择的产品是:{{chooseProduct}}</h1>
</div>
<script type="text/javascript">
// 产品组件
Vue.component("product-com",{
props:['product'], // 告知传入的数据从根组件过来
template:`<li>
<h3>产品名称:{{product.title}}</h3>
<h4>产品描述:{{product.brief}}</h4>
<p>产品价格:{{product.price}}</p>
<button @click="chooseEvent(product)">选择</button>
</li>`,
data () {
return {
}
},
methods:{
// 子组件向父组件传值必须有一个触发事件
chooseEvent (product) {
this.$emit("choosproduct",product)
}
}
})
// 根组件
var app = new Vue({
el:"#app",
data:{
proList:[
{
title:"产品1",
price:"10",
brief:"描述1"
},{
title:"产品2",
price:"20",
brief:"描述2"
}
],
chooseProduct:""
},
methods:{
chooseEvent (data) {
this.chooseProduct = data.title;
}
}
})
</script>
生命周期
<div id="app">
<h1>{{msg}}</h1>
<div :class="className"></div>
<hello-com v-if="isShow"></hello-com>
<hello-com v-show="isShow"></hello-com>
</div>
<script type="text/javascript">
let helloCom = Vue.component("hello-com", {
template: "<div><h1>{{hello}}</h1> <button @click='changeData'>修改数据</button> </div>",
data: function() {
return {
hello: 'helloWorld'
}
},
methods:{
changeData () {
this.hello = "helloXiaoMing"
}
},
beforeCreate () {
console.log('brforeCreate')
// 此时数据data和事件方法methods还未绑定到app对象上
},
created() {
console.log('create')
// 数据和方法绑定到应用对象上
},
beforeMount() {
// 渲染之前,根据数据生成的DOM对象是获取不到的
console.log('brforeMount')
},
mounted() {
// 渲染之后,可以获取到生成的DOM对象
console.log('mounted')
},
beforeUpdate() {
console.log('beforeUpdate')
// 数据更改,但内容未更改之前
},
updated() {
console.log('update')
// 内容已经更新完毕
},
beforeDestroy() {
console.log('beforeDestory')
// 应用销毁之前
},
destroyed() {
console.log('destory')
// 应用销毁之后
},
})
var app = new Vue({
el: "#app",
data: {
msg: "helloVue",
className: "redBg",
isShow:true
},
components:{
'hello-com':helloCom
},
beforeCreate() {
console.log('brforeCreate')
// 此时数据data和事件方法methods还未绑定到app对象上
console.log(this)
console.log(this.msg)
},
created() {
console.log('create')
// 数据和方法绑定到应用对象上
console.log(this)
console.log(this.msg)
},
beforeMount() {
// 渲染之前,根据数据生成的DOM对象是获取不到的
console.log('brforeMount')
let dom = document.querySelector("redBg")
console.log(dom)
},
mounted() {
// 渲染之后,可以获取到生成的DOM对象
console.log('mounted')
let dom = document.querySelector("redBg")
console.log(dom)
},
beforeUpdate() {
console.log('beforeUpdate')
// 数据更改,但内容未更改之前
},
updated() {
console.log('update')
// 内容已经更新完毕
},
beforeDestroy() {
console.log('beforeDestory')
// 应用销毁之前
},
destroyed() {
console.log('destory')
// 应用销毁之后
},
methods: {
clickEvent () {
},
isShow () {
this.isShow = !this.isShow
}
}
})
</script>
就先到这里,,,