vue part1 基础
0.准备
pycharm vue与EC6支持设定
https://www.cnblogs.com/infaaf/articles/9593237.html
chrome浏览器插件安装
完成后出现标记
vue页面标记需要使用vue.js非vue.min.js
调试页面
结构模型MVVM = m:model + v:view + vm
view(dom) ------dom listeners-----》 Model(data)
《------data bindings----
1. 调试运行Helloword
vue与jquery比较
vue
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> </head> <body> <div id="app"> <p>{{ message }}</p> <button v-on:click="clickfunc">点击</button> </div> <script> new Vue({ el:'#app', data:{ message:'before' }, methods:{ clickfunc:function () { this.message='after' } } }) </script> </body> </html>
jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <p id="pp">before</p> <button id="bt">点击</button> </div> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $('#bt').click(function () { $('#pp').text('after'); }) </script> </body> </html>
双向绑定例子
{{username}} 和input有默认值(绑定到username),{{username}} 随input输入框输入而变化。
<div id="app"> <input type="text" v-model="username"> <p>{{username}}</p> </div> <script src="../vue.js"></script> <script> const vm = new Vue({ el:'#app', data:{ username:'default name' }, }); </script>
2. 模版
模版示例
{{变量或者执行函数}} :属性中绑定 @监听
<div id="app"> <h2>1. 双大括号表达式</h2> <p>{{msg}}</p> <!-- 无v-model时,区分大小写 --> <p>{{msg.toUpperCase()}}</p> <p v-html="msg"></p> <p v-text="msg"></p> <h2>2. 指令 强制数据绑定,原Html语法绑定为变量</h2> <!--<img src={{imgurl}} alt=""> 标签属性不能用双大括号引用变量 --> <img v-bind:src="imgurl" alt=""> <img :src="imgurl" alt=""> <!-- 简写 --> <h2>3. 指令 绑定事件监听</h2> <button v-on:click="func1">点击1</button> <button @click="func1">点击2</button> <button @click='func2("abc")'>点击3</button> <!-- 回传参数 --> <button @click="func2(msg)">点击4</button> <!-- 回传变量 --> </div> <script src="../vue.js"></script> <script> const vm = new Vue({ el:'#app', data:{ msg:'default msg', imgurl:'http://www.tangvelley.com/static/images/bloglogo.png', }, methods:{ func1:function () { alert('ok') }, func2(content){ alert(content,'ES6简写fun语法'); }, } }); vm.msg='<B>msg22222</B>' </script>
显示效果
1. 双大括号表达式 <B>msg22222</B> <B>MSG22222</B> msg22222 <B>msg22222</B> 2. 指令 强制数据绑定,原Html语法绑定为变量 图片1 图片2 3. 指令 绑定事件监听 点击1 点击2 点击3 点击4
3. 计算属性和监视
case
计算computed 执行: 【1】初始化 【2】相关data发生改变 。 注意get 和set方法。set有缓存。
监视watch方法参考即可。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="app"> firstname<input type="text" v-model="firstname"> lastname <input type="text" v-model="lastname"> <hr> display1 <input type="text" v-model="fullname1"> <hr> display2 <input type="text" v-model="fullname2"> <p></p> display3 <input type="text" v-model="fullname3"> <p>{{fullname1}}</p> <p>{{fullname1add()}}</p> </div> <script src="../vue.js"></script> <script> const vm= new Vue({ el:'#app', data:{ firstname:'first', lastname:'last', }, computed:{ //计算 初始化显示 或者 data属性发生变化时执行 //函数方式 单向 fullname1(){ return this.firstname + ' ' + this.lastname }, // 对象 fullname3:{ //设置(set)fullname3 及 fullname3发生变化时set get(){ //计算并返回当前值,当需要读取当前值时回调 //回调函数(定义了,没有调用,却执行了) return this.firstname + ' ' + this.lastname; }, set(value){ //value 是fullname3最新值 //当属性发生改变时,更新相关属性 //回调函数,监视监视监视(不是设置)当前属性值(fullname3)变化 this.firstname=value.split(' ')[0]; this.lastname=value.split(' ')[1]; } }, }, methods:{ fullname1add(){ return this.firstname + ' ' + this.lastname }, }, watch:{ //监视 无初始化,当变化时触发 //名称为监视对象 firstname:function (newval, oldval) { console.log(newval); console.log(oldval); console.log(this); this.fullname2=newval + this.lastname } } }); //监视另一种写法 vm.$watch('lastname',function (newval, oldval) { this.fullname2 = this.firstname + newval }) </script> </body> </html>
methods computed watch区别
methods里面定义的函数,是需要主动调用的,而和watch和computed相关的函数,会自动调用,完成我们希望完成的作用
区别2
watch对象是变化的值,受影响对象作相关赋值操作
compute对象是受影响对象,直接return 相关结果
4. class与style绑定
主要利用v-bind ,
class 字符串形式:不同于默认html只读取第一个class,可以整合两个class(1个默认,1个变量)
:class对象形式:{},其中key常量,value变量从vue的data中获取。一般常用布尔形式 :class="{aclass:trueorfalse1,bclass:trueorfalse2}"注意引号value上没有
:style对象形式:参考上。注意 key与html style的key有不同。value为普通值string等,注意value无引号
case
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <style> .default { font-size: 50px; } .red { color:red; } .blue { color: blue; } </style> <script src="../vue.js"></script> </head> <body> <div id="app"> <h2 class="default" :class="extra_class">字符串方式,可以整合两个class,默认html只读第一个class</h2> <h2 :class="{blue:act1,red:act2}">对象方式用{},常量key,变量value到data取值,注意act1 无引号</h2> <button @click="fun1">点击</button> <h2 style="color: #00B0E8;font-size: small;">默认style</h2> <h2 :style="{color:v1,fontSize:v2}">对象style, 参数(如fontSize对应font-size)与htmlstyle参数略有不同</h2> </div> <script> const vm=new Vue({ el:'#app', data:{ extra_class:'red', act1:false, act2:true, v1:'green', v2:'30px', }, methods:{ fun1(){ this.extra_class='blue'; this.act1='true'; this.act2='false'; } } }) </script> </body> </html>
5. 条件渲染
v-if v-else v-show
case1
支持@click="state=!state"表达式
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <p v-if="state">true</p> <p v-else>false</p> <p v-show="state">show true</p> <p v-show="!state">show false</p> <button @click="state=!state">click</button> </div> <script> var vm = new Vue({ el:'#demo', data:{ state:false, } }) </script> </body> </html>
v-if 与v-show 在浏览器端差别
直接true false形式
<p v-show="true">默认显示</p> <p v-show="false">默认不显示</p> <p v-if="false">true</p> <p v-else>false</p>
6. 列表
6.1 列表渲染
数组(列表)遍历
case 1
:key=”index“ 用途 https://www.cnblogs.com/tim100/p/7262963.html 影响渲染
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <ul> <li v-for="(person,index) in persons" :key="index"> {{index}}--{{person.name}}--{{person.age}} </li> </ul> </div> <script> new Vue({ el:'#demo', data:{ persons:[ {name:'n1',age:18}, {name:'n2',age:20}, {name:'n3',age:22}, {name:'n4',age:24}, ] } }) </script> </body> </html>
注意数组方法
1、调用$set方法: this.arr.$set(index, val); 1 2、调用splice方法: this.arr.splice(index, 1, val); 1 二、合并数组: this.arr = this.arr.concat(anotherArr); 1 三、清空数组: this.arr = []; 1 四、主要的数组方法: 1、变异方法(修改了原始数组),vue为触发视图更新,包装了以下变异方法: push() pop() shift() unshift() splice() //无论何时,使用该方法删除元素时注意数组长度有变化,bug可能就是因为她 sort() reverse() 1 2 3 4 5 6 7 2、非变异方法(不会修改原始数组而是返回一个新数组),如concat()、filter(),使用时直接用新数组替换旧数组,如上面的合并数组例子。 五、注意: //以下操作均无法触发视图更新 this.arr[index] = val; this.arr.length = 2; 1 2 3 详细了解请参考vue官方文档数组变动检测。
数组变化---视图是否变化---数组是否变化规则
vue监视对象是否发生变化,不监视对象内部。 数组方法已被重写为vue变异方法
https://blog.csdn.net/fengjingyu168/article/details/79782957 1、数组变化-视图更新-原始数组变化 push() pop() shift() unshift() splice() sort() reverse() 2、数组变化-视图更新-原始数组不变 filter() concat() slice() 3、数组变化-视图不变 通过索引直接设置项 this.items[2] = {name: 'abc'} 1 解决方式1:使用$set this.$set(app.items, 2, {name: 'abc'}) 1 解决方式2:使用splice() this.items[2].splice(2, 1, {name: 'abc'}) 1 修改数组长度 this.items.length = 2 1 解决方法: this.items.splice(2)
case2
添加删除与更新方法,注意vue变异方法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <ul> <!-- index值随页面变化而变化,删除0号,原1号的index变为0 --> <!-- key值这里选了index,实际最好选择不变的数据id --> <li v-for="(person,index) in persons" :key="index"> {{index}}--{{person.name}}--{{person.age}} <button @click="deleteP(index)">删除</button> <button @click="updateP(index,{name:'zz',age:25})">更新</button> </li> </ul> </div> <script> new Vue({ el:'#demo', data:{ persons:[ {name:'n1',age:18}, {name:'n2',age:20}, {name:'n3',age:22}, {name:'n4',age:24}, ] }, methods:{ deleteP:function (index) { this.persons.splice(index,1) }, updateP (index,newP){ // this.persons[index]=newP 数组变化,页面不变,详见Vue变异方法说明 this.persons.splice(index,1,newP) } } }) </script> </body> </html>
v-for遍历对象(比较少用)
case3
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <ul> <!-- index值随页面变化而变化,删除0号,原1号的index变为0 --> <!-- key值这里选了index,实际最好选择不变的数据id --> <li v-for="(person,index) in persons" :key="index"> {{index}}--{{person.name}}--{{person.age}} <button @click="deleteP(index)">删除</button> <button @click="updateP(index,{name:'zz',age:25})">更新</button> </li> </ul> <hr> <ul> <li v-for="(item,key) in persons[1]" :key="key"> {{key}}:{{item}} </li> </ul> </div> <script> new Vue({ el:'#demo', data:{ persons:[ {name:'n1',age:18}, {name:'n2',age:20}, {name:'n3',age:22}, {name:'n4',age:24}, ] }, methods:{ deleteP:function (index) { this.persons.splice(index,1) }, updateP (index,newP){ // this.persons[index]=newP 数组变化,页面不变,详见Vue变异方法说明 this.persons.splice(index,1,newP) } } }) </script> </body> </html>
6.2 列表搜索排序
补充,filter方法
https://blog.csdn.net/bossxu_/article/details/80756563 https://blog.csdn.net/tang15886395749/article/details/65629898 filter(item => item) filter((item,index,arr)=>{ return item>2 })
case
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo2"> <input type="text" v-model="searchname"> <ul> <!--<li v-for="(person,index) in persons">--> <!--{{index}}--{{person.name}}--{{person.age}}--> <!--</li>--> <li v-for="(person,index) in filterpersons"> {{index}}--{{person.name}}--{{person.age}} </li> </ul> <button @click="setOrderType(1)">age升序</button> <button @click="setOrderType(2)">age降序</button> <button @click="setOrderType(0)">原顺序</button> </div> <script> new Vue({ el:'#demo2', data:{ searchname:'', orderType:0, // 0原顺序, 1升序, 2降序 persons:[ {name:'n1',age:28}, {name:'n2',age:20}, {name:'n3',age:22}, {name:'n4',age:24}, ] }, computed:{ filterpersons(){ // let retperson; // retperson=this.persons.filter(person=>person.name.indexOf(this.searchname)!==-1); const {searchname,persons,orderType}= this; let retperson; retperson=persons.filter(person => person.name.indexOf(searchname)!==-1); if (orderType!==0){ retperson.sort(function (person1,person2) { //负数p1在前 if(orderType===1){ return person1.age-person2.age; }else{ return person2.age-person1.age; } }) } return retperson } }, methods:{ setOrderType(type){ this.orderType=type; } } }) </script> </body> </html>
7. 事件处理
绑定监听
多种绑定方式
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <button @click="test1()">bt1</button> <button @click="test2('abc')">bt2</button> <button @click="test3">bt3</button> </div> <script> let vm = new Vue({ el:'#demo', data:{ test1(){ alert(1); }, test2(a){ alert(a); } }, methods:{ test3(){ alert(3); } } }) </script> </body> </html>
$event
常用event
event.target.nodeName //获取事件触发元素标签name
event.target.id //获取事件触发元素id
event.target.className //获取事件触发元素classname
event.target.innerHTML
event.target.value // input值
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <button @click="test5">bt5</button> <!--可以省略$event --> <button @click="test6(6,$event)">bt6</button> </div> <script> let vm = new Vue({ el:'#demo', data:{ test5(event){ alert(event.target.innerHTML); }, test6(num,event){ alert(num + event.target.innerHTML); } } }) </script> </body> </html>
事件修饰符(如@click)
@click.stop='xxx' 停止冒泡。否则显示inner后再显示out
@click.prevent='xx' 默认行为阻止
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <div style="width: 200px;height: 200px;background-color: burlywood" @click="sp1"> <div style="width: 50px;height:50px;background-color: #00B0E8" @click.stop="sp2"></div> </div> <a href="http://www.baidu.com" @click.prevent="sp3">点击</a> </div> <script> let vm = new Vue({ el:'#demo', data:{ sp1(){ alert('out'); }, sp2(){ alert('inner'); }, sp3(){ alert('333'); }, }, }) </script> </body> </html>
按键修饰符
需求:按键enter时触发
@keyup.enter="test" 键盘按键的修饰符,监听enter。不加.enter会监听所有按键。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <input type="text" @keyup="sp4"> <input type="text" @keyup.13="sp5"> <input type="text" @keyup.enter="sp5"> <!-- 少数特殊key直接写名称 --> </div> <script> let vm = new Vue({ el:'#demo', data:{ sp4(event){ if(event.keyCode===13) { alert(event.target.value + event.key + event.keyCode) } }, sp5(event){ alert(event.target.value); } }, }) </script> </body> </html>
8.表单数据的自动收集
html 表单中的name改为v-model 。
form头的 onSubmit改为@submit.prevent
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demoform"> <form action="/xxx" @submit.prevent="handleSubmit"> <span>用户名</span><input type="text" v-model="username"><br> <span>密码</span><input type="text" v-model="pwd"><br> <span>性别></span> <input type="radio" v-model="gender" value="女" id="female"><label for="female">女</label> <input type="radio" v-model="gender" value="男" id="male"><label for="male">男</label><br> <span>爱好</span> <input type="checkbox" v-model="hobbit" value="basket" id="basket"><label for="basket">篮球</label> <input type="checkbox" v-model="hobbit" value="foot" id="foot"><label for="foot">足球</label><br> <span>城市</span> <select v-model="yourcity"> <option value="">未选择</option> <option :value="city.id" v-for="(city,index) in citys" :key="index">{{city.name}}</option> </select><br> <span>介绍</span> <textarea v-model="intro" id="" cols="30" rows="10"></textarea> <input type="submit" value="注册 "> </form> </div> <script> new Vue({ el:'#demoform', data:{ username:'', pwd:'', gender:'男', hobbit:['foot'], citys:[{id:1,name:'上海'},{id:2,name:'北京'},{id:3,name:'广州'}], yourcity:3, intro:'', }, methods:{ handleSubmit(){ console.log(this.username,this.hobbit,this.yourcity); } } }) </script> </body> </html>
9. vue 生命周期
略
10. 过渡&动画
实际操作css的transition和animation
效果及状态详细https://cn.vuejs.org/v2/guide/transitions.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> <style> .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; } </style> </head> <body> <div id="demo"> <button @click="show=!show">toggle</button> <p v-show="show">内容1</p> <transition name="fade"> <!--name 用于css样式名 --> <p v-if="show">内容2</p> </transition> </div> <script> new Vue({ el:'#demo', data:{ show:true, } }) </script> </body> </html>
11.过滤器(格式化)
时间格式化
1. moment插件http://momentjs.cn/
2. Vue.filter功能
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> <style> .fade-enter-active, .fade-leave-active { transition: opacity .5s; } .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; } </style> </head> <body> <div id="demo"> <p>{{date1}}</p> <p>{{date1 | dateStr}}</p> <p>{{date1 | dateStr('YYYY-MM-DD')}}</p> </div> <script src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"></script> <script> Vue.filter('dateStr',function (val,formatstr='YYYY-MM-DD HH:mm:ss a') { return moment(val).format(formatstr); // return moment(val).format(formatstr || 'YYYY-MM-DD HH:mm:ss a') }); new Vue({ el:'#demo', data:{ date1:new Date(), } }) </script> </body> </html>
12. 指令补遗
列表
v-text 更新textConten
v-html 更新元素InnerHTML
v-if ,v-show,v-else,v-for,
v-on,简写为 @
v-bind 简写为 :
v-model双向绑定
ref 唯一标识
v-cloak 防止闪现表达式
内容显示标签
v-model
一般位于input等form标签中,放在span中不能令span产生内容 。v-text v-html改变span标签内内容
双向绑定
v-text v-html比较
v-text 原样显示
v-html 会解析标签,无含义的标签同html无效果。但v-html容易受XSS攻击。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <span v-text="msg"></span><br> <span v-html="msg2"></span> </div> <script> new Vue({ el: '#demo', data: { msg: '<b>aaa</b>', msg2: '<a>bbb</a>', } }) </script> </body> </html>
{{}}与 v-text比较
都是单向绑定, 数据对象改变影响页面值改变,反之不行。基本相同。
{{}}视作v-text简写形式。
当网速过慢时页面显示暴露{{}}
v-text与 v-once单次绑定
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo"> <span v-text="msg">{{msg}}</span><br> <span v-once>{{msg2}}</span> <button @click="change">点击改变</button> </div> <script> new Vue({ el: '#demo', data: { msg: 'aaa', msg2: 'bbb', }, methods:{ change(){ this.msg+='msg1'; this.msg2+='msg2'; }, } }) </script> </body> </html>
ref
标识符,可以方便定位, 通过textContent 或者innerHTML获取标签内容
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue </title> <script src="../vue.js"></script> </head> <body> <div id="demo2"> <p ref="mycontent">{{msg}}</p> <button @click="hint">点击提示其他标签</button> </div> <script> new Vue({ el: '#demo2', data: { msg: 'aaa', msg2: 'bbb', }, methods:{ hint(){ console.log(this.$refs.mycontent.textContent) }, } }) </script> </body> </html>
v-cloak
利用解析完成后不再存在特性,设置style display none 等
自定义指令
局部与全局指令定义位置与生效区间不同。
案例略
13 插件
自定义插件 vue-mypluginnamexxx.js。 注意需要向外暴露 window.xxx
引用时放在vue.js的引用之后。
script实际使用时,Vue.use(xxx)
14. 组件components
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/vue/2.2.2/vue.js"></script> </head> <body> <div id="app"> <parent></parent> </div> <script> let child={ template:'<div>{{myMsg}}</div>', props:{myMsg:String} }; let parent={ template:'<div><child :my-msg="key1"></child></div>>', components:{child}, data(){ return { 'key1':'abc' } } }; new Vue({ el:'#app', components:{parent} }) </script> </body> </html>
说明:
使用到组件(html标签)时,需要定义components
子组件中,使用到动态值需要从父组件中传递时,使用props 。 在父组件中绑定,并使用data回归。
步骤: 1 import引入 2 components {}注册为标签 3 使用
引用父组件变量props申明。