Vue基础篇(二)
|字数总计:4.2k|阅读时长:20分钟|阅读量:|
模板语法
插值表达式
利用插值表达式来输出信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="app"> <h1> {{msg}} </h1> </div>
<script type="text/javascript"> var app = new Vue({ el:"#app", data:{ msg:"hello Vue", }, }) </script>
|
v-once
属性:
v-once
是只渲染生成一次,此时如果在控制台更改 app.msg
的值则它并不会改变
插值表达式还支持简单运算:
字符串拼接:
1
| <h1>{{firstname + lastname}}</h1>
|
运算:
输出结果就是 3 而不是 1 + 2
还支持三元运算:
1
| <div>{{isVip?"VIP用户":"普通用户"}}</div>
|
若 isVip
为 true
则显示 VIP用户,反之则显示 普通用户
v-html
v-html
也可以用来输出信息,但是这么做并不推荐,因为不是怎么安全,可能会引发 XSS 问题。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <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
是动态属性绑定,可以简写为一个冒号 :
1 2 3 4 5 6 7 8 9 10 11 12 13
| <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
是事件绑定,可以绑定监听事件,也可简写为 @
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <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 输入绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <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 判断
例如:
1 2 3 4 5 6 7 8 9 10 11 12
| <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 列表渲染
循环渲染一个列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <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
值,循环对象数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <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>
|
还是上面那个对象数组,进行循环对象:
1 2 3
| <ul> <li v-for="(item,index) in students[0]" :key="index">{{item}}</li> </ul>
|
条件循环渲染:
1 2 3 4 5 6
| <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 官方文档
侦听属性
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <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
计算属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| <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> <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(""); }, } }, }) </script>
|
那么在例子中 {{firstname+lastname}}
和 {{fullname}}
有什么区别呢,因为在计算属性中,只要计算一次,就会将计算结果进行缓存,所以当这个数据需要大量显示的时候,我们可以使用计算属性来提高性能,就不用每显示一次就要进行计算一次。
循环优化的原理:在前面的例子中我们有一个条件循环偶数年龄的学生,我们先进行计算得出偶数学生的数组,就不用循环之后再进行判断,直接把偶数的对象先计算出来再使用,只循环需要的,而且它最大的优点就是可以先把计算结果先缓存下来,只要内容不改变他就可以直接拿来用,从而提高性能
事件传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <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>
|
既能传入事件对象也能传入参数
事件修饰符
1 2 3
| <div @click="one"> <button type="button" @click.stop="two">点击</button> </div>
|
事件修饰符 .stop
用来阻止冒泡事件,如果没有加修饰符的话,当点击事件 two
被触发时,事件 one
也会被触发,加上修饰符之后就不会了
1 2 3 4
| <form method="post"> <input type="submit" value="提交1"/> <input @click.prevent="" type="submit" value="提交2"/> </form>
|
默认情况下点击 提交1 会有一个 POST 请求被提交,通过 .pervent
修饰符阻止默认行为
1
| <button type="button" @click.once="">只触发一次点击</button>
|
.once
修饰符是只触发一次,第二次点击就没有效果了
1
| <input type="text" @keydown.enter="search" value="回车" />
|
keydown
是按键绑定,监听键盘按键的动作
1
| <input type="text" @keydown.enter.f1="search" value="回车和F1" />
|
同时绑定两个按键
1
| <button type="button" @click.ctrl="ctrlEvent">按住Ctrl事件</button>
|
按住 Ctrl
键再点击按钮才会触发事件,但是如果按住 Ctrl
和其他键也会触发,就需要精确的只识别 Ctrl
键:
1
| <button type="button" @click.ctrl.exact="ctrlEvent">按住Ctrl事件</button>
|
1 2 3 4 5 6 7 8 9
| <script type="text/javascript"> Vue.config.keyCodes.f1 = 112 var app = new Vue({ el:"#app", data:{ }, }) </script>
|
自定义按键修饰符
Class 与 Style 样式绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <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>
|
内联样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <div id="app"> <div style="width: 100px;height: 100px;background-color: skyblue;" :style="{border: borderWidth+'px solid red',padding:paddingWidth+'px'}"></div> <div :style="styleObj"></div> <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>
|
动态组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <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', 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) { this.com = this.$options.components['com'+id] } }, components:{ com1,com2,com3,com4 } }) </script>
|
组件传值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <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>
|
生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| <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') }, created() { console.log('create') }, beforeMount() { console.log('brforeMount') }, mounted() { 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') console.log(this) console.log(this.msg) }, created() { console.log('create') console.log(this) console.log(this.msg) }, beforeMount() { console.log('brforeMount') let dom = document.querySelector("redBg") console.log(dom) }, mounted() { 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>
|
就先到这里,,,