vue官网
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="js/vue.js" > </script > <style > [v-cloak] { display :none; } </style > </head > <body > <div id ="app" > <h3 id ="msg" > 传统方式</h3 > <h1 v-cloak > {{msg}}</h1 > <h2 v-cloak > {{exam}}</h2 > <h2 v-cloak > {{'年龄:'+exam}}</h2 > <h1 v-bind:title ="message" > 鼠标悬停几秒钟查看此处动态绑定的提示信息!</h1 > </div > </body > <script > var app=new Vue ({ el :'#app' , data : { msg : 'Vue修改' , exam :19 +1 , message :'页面加载于' +new Date ().toLocaleString () } }); </script > </html >
解决屏闪 /* 解决屏闪 */ 样式 [v-cloak]{ display:none; } 界面 <h2 v-cloak > {{exam}}</h2 > JS var app=new Vue({ //ID el:'#app', //属性 data: { msg: 'Vue修改', exam:19+1, message:'页面加载于'+new Date().toLocaleString() } });
常用指令 v-cloak 解决闪屏 样式
[v-cloak] { display :none; }
界面
js
var app=new Vue ({ el :'#app' , data : { msg : 'Vue修改' , exam :19 +1 , message :'页面加载于' +new Date ().toLocaleString () } });
v-text 显示数据 理解
界面
js
var app=new Vue ({ el :'#app' , data : { message :'页面加载于' +new Date ().toLocaleString (), msg :'你好temo' } });
v-html显示识别html 理解
界面
js
var app=new Vue ({ el :'#app' , data : { jk :'<i>nh1<i/>' } });
v-pre 不编译 理解
界面
js
var app=new Vue ({ el :'#app' , data : { msg :'你好temo' , } });
v-once 只渲染一次 理解
界面
<h3 v-once > 乌克兰{{wkl}}</h3 >
js
var app=new Vue ({ el :'#app' , data : { wkl :'admi123456' , } });
v-show 隐藏显示 理解
v-show="条件" 切换元素的display 隐藏显示
界面
<h1 v-show ="1==1" > v-show</h1 >
v-model 数据双向绑定 理解
界面
<input type ="text" v-model ="info" />
js
var app=new Vue ({ el :'#app' , data : { info :'文本框' } });
v-if 判断 理解
条件判断 v-if="条件" 判断是否满足 满足显示一块 不满组不显示
界面
<div v-if ="1==0" > 大家好</div >
v-else 否则 理解
v-if="条件" v-else if判断 满足if里面的 不满足就else里面的
界面
<div > <div v-if ="Math.random()>0.5" > ture </div > <div v-else > false</div > </div >
v-else-if 理解
界面
<div v-if ="type === 'A'" > A </div > <div v-else-if ="type === 'B'" > B </div > <div v-else-if ="type === 'C'" > C </div > <div v-else > Not A/B/C </div >
v-for循环 理解
for 循环 v-for="自定义循环名字 in 循环的变量名" for循环 显示数据{{自定义名字}} v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示: <div v-for ="item in items" :key ="item.id" > {{ item.text }} </div >
界面
<ul > <li v-for ="item in items" > {{item}}</li > </ul >
js
var app=new Vue ({ el :'#app' , data : { items :[1 ,2 ,3 ,6 ,7 ] } });
v-on绑定事件监听器 理解
v-on:事件="变量" 绑定事件监听器 v-on:click="" v-on:mouseover="" ... 缩写:@ .stop - 调用 event.stopPropagation()。 .prevent - 调用 event.preventDefault()。 .capture - 添加事件侦听器时使用 capture 模式。 .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。 .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。 .native - 监听组件根元素的原生事件。 .once - 只触发一次回调。 .left - (2.2.0) 只当点击鼠标左键时触发。 .right - (2.2.0) 只当点击鼠标右键时触发。 .middle - (2.2.0) 只当点击鼠标中键时触发。
界面
<button v-on:click ="dj" > v-on:click</button > <button v-on:mouseover ="yr" > v-on:mouseover</button >
js
var app=new Vue ({ el :'#app' , data : { }, methods :{ dj :()=> { alert ('v-on:click' ); }, yr :()=> { alert ('v-on:mouseover' ); } } });
v-bind 动态绑定属性 理解
v-bind:属性="变量" 动态地绑定一个或多个 attribute 属性 v-bind:src || v-bind:width || v-bind:height... 缩写: :
界面
<img v-bind:src ="vimg" v-bind:width ="vimgw" v-bind:height ="vimgh" >
js
var app=new Vue ({ el :'#app' , data : { vimg :'./img/3210.webp' , vimgw :'700px' , vimgh :'500px' } });
示例
<img v-bind:src ="imageSrc" > <button v-bind: [key ]="value" > </button > <img :src ="imageSrc" > <button : [key ]="value" > </button > <img :src ="'/path/to/images/' + fileName" > <div :class ="{ red: isRed }" > </div > <div :class ="[classA, classB]" > </div > <div :class ="[classA, { classB: isB, classC: isC }]" > <div :style ="{ fontSize: size + 'px' }" > </div > <div :style ="[styleObjectA, styleObjectB]" > </div > <div v-bind ="{ id: someProp, 'other-attr': otherProp }" > </div > <div v-bind:text-content.prop ="text" > </div > <my-component :prop ="someThing" > </my-component > <child-component v-bind ="$props" > </child-component > <svg > <a :xlink:special ="foo" > </a > </svg >
事件处理 带参数也有默认的event 不带参数也有
点击调方法 <button v-on :click="sj" >事件1 </button> var app=new Vue ({ el :'#app' , data : { num :1 }, methods : { sj :function ( ){ this .num ++; console .log (this ); } } })
方法带括号 <button v-on:click ="sj()" > 事件1</button >
方法带参数 <button @click="cc(3,6)" >传参数</button> var app=new Vue ({ el :'#app' , data : { num :1 }, methods : { cc :function (a,b ){ this .num =a+b; } } })
data变量参数 <button @click="cc2(num,6)" >传参数</button> var app=new Vue ({ el :'#app' , data : { num :1 }, methods : { cc2 :function (a,b ){ this .num =a+b; console .log (event.target ); } } })
点击直接运行不调方法 <button v-on:click ="num--" > 事件2</button >
多个按钮输出当前按的按钮 <button @click="hello" >A</button> <button @click ="hello" > B</button > <button @click ="hello" > C</button > var app=new Vue ({ el :'#app' , data : { num :1 }, methods : { hello :function (event ){ alert ("我是" +event.target .innerHTML ); } } })
事件修饰符 冒泡 在事件后加.stop
<div @click="show('父')" > 父盒子 <div @click.stop ="show('子')" > 子盒子 </div> </div> var app=new Vue ({ el :"#app" , data : { num :0 }, methods : { show : function (info ) { console .log (info); } } });
只触发一次 事件后加.once
<!--只会触发一次 点了一次就没用了--> <a v-on:click.once ="doThis" > ayd1</a > var app=new Vue ({ el :"#app" , data : { num :0 }, methods : { doThis :function ( ){ alert ("点击了!" ); } } });
阻止事件的默认行为 事件后加.prevent
h1>练习2 </h1> <a href ="http://www.baidu.com" @click.prevent ="lj" > 百度</a > var app=new Vue ({ el :"#app" , data : { num :0 }, methods : { lj :function ( ){ alert ("点击了链接!" ); } } });
通过冒泡判断点的按钮 <h1>练习</h1> <div @click ="dj" > <button > A</button > <button > B</button > <button > C</button > </div > var app=new Vue ({ el :"#app" , data : { num :0 }, methods : { dj :function (event ) { console .log (event.target .innerHTML ); } } });
按键修饰符 .enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
回车提交 <form> Name :<input type ="text" v-model ="name" /> Password :<input type ="password" id ="pa" v-model ="pass" @keyup.enter ="login" /> <input type ="button" value ="登入" > </form > var app=new Vue ({ el :'#app' , data : { name :"" , pass :"" }, methods :{ login :function ( ){ console .log (this .name ); console .log (this .pass ); this .name ='' , this .pass ='' } } });
del删除密码 <h1>按del</h1> <form > Name:<input type ="text" v-model ="name" /> Password:<input type ="password" v-model ="pass" @keyup.delete ="de" /> <input type ="button" value ="登入" > </form > var app=new Vue({ el:'#app', data: { name:"", pass:"" }, methods:{ //按删除 就删除密码 de:function(){ this.pass='' } } });
自定义按键名字 <h1>自定义</h1> <input type ="text" @keyup.da ="r" /> Vue .config .keyCodes .da =82 ; var app=new Vue ({ el :'#app' , data : { name :"" , pass :"" }, methods :{ r :function ( ){ console .log ("按了R" ); } } });
属性绑定 href绑定 <a v-bind :href="href" >去百度2 </a> <a :href ="href" > 去百度2</a > var app=new Vue ({ el :"#app" , data : { href :"http://www.baidu.com" , } });
图片循环切换 <img :src="arr[index]" width="500px" height="300px" ><button @click ="huan2()" > 换</button > var app=new Vue ({ el :"#app" , data : { href :"http://www.baidu.com" , info :"今天送皮肤" , imgurl :'img/11.webp' , id :0 , arr :['img/11.webp' ,'img/12.webp' ,'img/22.webp' ,'img/3210.webp' ], index :0 , h1ar :'' }, methods :{ huan2 :function ( ){ this .index ++; if (this .index ==this .arr .length ){ this .index =0 ; } } } });
不使用v-model实现双向绑定 <h1>{{h1ar}}</h1> <input type ="text" :value ="h1ar" @keyup ="gb" /> var app=new Vue ({ el :"#app" , data : { }, methods :{ gb :function ( ){ this .h1ar =event.target .value ; } } });
样式绑定 对象语法绑定class 样式
.atice { border :10px solid pink; width : 100px ; height : 100px ; } .err { background-color :aquamarine }
html
<!-- 定义:atice是样式的名称:随便名字 随便名字可以在下面进行true (使用这个样式) || false (不使用这个样式) --> <h1 > 对象语法绑定</h1 > <div :class ="{atice:isActive,err:iserr}" > 用对象 </div >
js
var app = new Vue ({ el : "#app" , data : { val : "" , isActive :false , iserr : true } });
数组语法绑定class 样式
.atice { border :10px solid pink; width : 100px ; height : 100px ; } .err { background-color :aquamarine }
html
<!-- 定义[自定义名字1 ,自定义名字2 ] data里面 自定义名字1 ="样式表名" --> <h1 > 数组语法绑定</h1 > <div :class ="[c1,c2]" > 用数组 </div >
js
var app = new Vue ({ el : "#app" , data : { c1 :'atice' c2 :'err' , } });
对象数组混合 <h1>混合使用</h1> <div :class ="[c3,{err:herr}]" > 混合使用 </div > var app = new Vue ({ el : "#app" , data : { c3 :'atice' , herr :true }, methods : { nj : function ( ) { this .val = event.target .value ; }, dxhys :function ( ) { this .isActive = !this .isActive ; this .iserr =!this .iserr ; }, szhys :function ( ){ this .c2 ='' ; } }, });
分支 <div id="app" > <!--v-if 返回true false 控制标签的隐藏显示--> <div v-if ="score>=90" > 优秀</div > <div v-else-if ="score>=80" > 中等</div > <div v-else-if ="score>=70" > 一般般</div > <div v-else > 补课</div > <hr> <!--v-show 标签隐藏显示--> <div v-show ="flag" > 目标</div > </div> var app = new Vue ({ el : "#app" , data : { score :76 , flag :false }, methods : { }, });
循环 循环数组 界面
<h1 > 循环数组</h1 > <ul > <li v-for ="(fls,i) in fruit" :class ="i%2!=0?'ls':''" > {{i}} {{fls}}</li > <li v-for ="fls,i in fruit" :class ="{ls:i%2!=0,ls2:i%2==0}" > {{i}} {{fls}}</li > </ul >
js
var app = new Vue ({ el : "#app" , data : { fruit : ["apple" , "orange" , "banana" , "watermelon" , "almond" ], }, methods : {}, });
循环对象 数组里有对象 界面
<h1 > 循环对象 数组里面有对象</h1 > <table border ="1px" cellspacing ="0px" width ="500px" height ="200px" style ="text-align:center" > <tr > <td > ID</td > <td > 姓名</td > <td > 年龄</td > </tr > <tr v-for ="st in mystud" :key ="st.id" > <td > {{st.id}}</td > <td > {{st.name}}</td > <td > {{st.age}}</td > </tr > </table >
js
var app = new Vue ({ el : "#app" , data : { mystud : [ { id : 1 , name : "st1" , age : 18 }, { id : 2 , name : "st2" , age : 20 }, { id : 3 , name : "st3" , age : 19 }, ] }, methods : {}, });
循环对象 <h1 > 循环对象</h1 > <table border ="1px" cellspacing ="0px" width ="500px" height ="200px" style ="text-align:center" > <tr > <td > 下标</td > <td > 名称</td > <td > 值</td > </tr > <tr v-for ="(ms,name,index) in mys" > <td > {{index}}</td > <td > {{name}}</td > <td > {{ms}}</td > </tr > </table >
js
var app = new Vue ({ el : "#app" , data : { mys :{ id :101 ,name : "st101" , age :90 }, }, methods : {}, });
样式绑定 循环 选项卡切换图片示例 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" /> <meta http-equiv ="X-UA-Compatible" content ="IE=edge" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <title > Document</title > <script src ="js/vue.js" > </script > <style > ul li { float : left; width : 100px ; list-style : none; height : 50px ; border : 1px solid pink; text-align : center; line-height : 50px ; } .bg { background-color : pink; } #d2 { margin-top : 30px ; margin-left : 30px ; } </style > </head > <body > <div id ="app" > <ul > <li @click ="cf(fl.id)" :class ="currid==fl.id ?'bg':''" v-for ="fl in flis" > {{fl.name}}</li > </ul > <br > <div id ="d2" > . <img v-if ="currid==f.id" v-for ="f in flis" :src ="f.imgurl" width ="500px" height ="300px" /> </div > </div > </body > <script > var app = new Vue ({ el : "#app" , data : { flis : [ { id : 1 , name : "选项卡1" , imgurl : "img/11.webp" }, { id : 2 , name : "选项卡2" , imgurl : "img/12.webp" }, { id : 3 , name : "选项卡3" , imgurl : "img/22.webp" }, ], currid :1 }, methods : { cf : function (a ) { this .currid = a; }, }, }); </script > </html >
表单 文本框 界面
<form action ="" > <span > 姓名:</span > <span > <input type ="text" v-model ="una" /> </span > <button type ="submit" @click.prevent ="tj" > 提交</button > </form >
js
var app = new Vue ({ el : "#app" , data : { una :'' }, methods : { tj :function ( ) { console .log ("姓名:" +this .una ); } }, });
下拉框 界面
<select v-model ="city" > <option disabled > 请选择城市</option > <option value ="北京" > 北京</option > <option value ="上海" > 上海</option > <option value ="南京" > 南京</option > <option value ="广州" > 广州</option > <option value ="深圳" > 深圳</option > </select >
js
var app = new Vue ({ el : "#app" , data : { city :'请选择城市' }, methods : { tj :function ( ) { console .log ("下拉框:" +this .city ); } }, });
单选框 界面
<input type ="radio" value ="男" v-model ="sex" /> 男<input type ="radio" value ="女" v-model ="sex" /> 女
js
var app = new Vue ({ el : "#app" , data : { sex :'男' , ches :['打球' ], city :'请选择城市' , ms :'' }, methods : { tj :function ( ) { console .log ("性别:" +this .sex ); } }, });
多选框 界面
<input type ="checkbox" value ="打球" v-model ="ches" /> 打球<input type ="checkbox" value ="打游戏" v-model ="ches" /> 打游戏<input type ="checkbox" value ="游泳" v-model ="ches" /> 游泳
js
var app = new Vue ({ el : "#app" , data : { ches :['打球' ] }, methods : { tj :function ( ) { console .log ("复选框:" +this .ches ); } }, });
文本域 界面
<textarea v-model ="ms" rows ="5" cols ="50" placeholder ="请输入描述" > </textarea >
js
var app = new Vue ({ el : "#app" , data : { ms :'' }, methods : { tj :function ( ) { console .log ("描述:" +this .ms ); } }, });
表单修饰符 number 数值 年龄:<input type ="text" v-model.number ="age" v-focus /> <br />
trim 去空格 地址:<input type ="text" v-model.trim ="address" v-color ="bgc" /> <br />
lazy 失去焦点改变 姓名:<input type ="text" v-model.lazy ="stname" v-colorg ="bg2" />
自定义指令 生命周期:bind inserted update componentUpdate unbid
bind:初始化
inserted:挂载完毕
update数据更新后
componentUpdate 元素更新后
unbind卸载
三个参数 el,binding vnode
// ele指指令所在的元素
// binding包含指令的详细信息 ,比如读取参数
// vnode是虚拟节点对象,比如获取组件对象
自定义全局指令 不带参数 定义在new Vue的前面
Vue .directive ("focus" , { inserted : function (el ) { el.focus (); }, });
使用 v-focus v-上面自定义的名字
年龄:<input type ="text" v-model.number ="age" v-focus /> <br />
自定义全局指令 带参数 多个值
Vue .directive ("color" , { bind : function (el, bindc ) { el.style .backgroundColor = bindc.value .bgcolor ; el.style .color = bindc.value .color ; }, }); var app = new Vue ({ el : "#app" , data : { bgc : { color : "red" , bgcolor : "pink" , } }, methods : { dl : function ( ) { console .log ("年龄:" + this .age + 10 ); console .log ("地址:" + this .address ); console .log ("姓名:" + this .stname ); }, } });
使用
地址:<input type ="text" v-model.trim ="address" v-color ="bgc" /> <br />
单个值
Vue .directive ("colorg" , { bind : function (el, bindcj ) { el.style .backgroundColor = bindcj.value ; }, }); var app = new Vue ({ el : "#app" , data : { bg2 : "pink" , }, methods : { dl : function ( ) { console .log ("年龄:" + this .age + 10 ); console .log ("地址:" + this .address ); console .log ("姓名:" + this .stname ); }, } });
使用
姓名:<input type ="text" v-model.lazy ="stname" v-colorg ="bg2" />
自定义局部指令 加一个节点directives
var app = new Vue ({ el : "#app" , data : { co :{ color :'pink' , color2 :'red' } }, methods : { }, directives : { focuc : { inserted : function (el ) { el.focus (); }, }, col :{ bind : function (el,bindc ){ el.style .color =bindc.value .color } } }, });
使用
姓名:<input type ="text" v-model.lazy ="stname" v-col ="co" /> <br />
计算属性computed 计算属性和直接调方法区别: 计算属性有缓存 调用多次只执行一次 方法调用多少次就执行多少次
计算属性可以直接赋值 不需要在定义
官网的一句话:对于任何复杂逻辑,你都应当使用计算属性。
methods方法和computed计算属性,两种方式的****最终结果确实是完全相同
界面
<div id ="app" > <h1 > 计算属性:{{msg}}</h1 > <h1 > 计算属性:{{msg2}}</h1 > <input type ="text" v-model ="nr" /> <h1 > 计算属性:{{zhuan}}</h1 > <h1 > 方法{{msg3()}}</h1 > </div >
js
var app = new Vue ({ el : "#app" , data : { msg : '你好' , nr :'' }, methods : { msg3 :function ( ){ console .log ('方法...' ) return this .nr .substring (0 ,1 ).toUpperCase ()+this .nr .substring (1 ).toLowerCase (); } }, computed :{ msg2 : function ( ){ return this .msg .split ('' ).reverse ().join ('' ); }, zhuan :function ( ){ console .log ("计算中..." ) return this .nr .substring (0 ,1 ).toUpperCase ()+this .nr .substring (1 ).toLowerCase (); } } });
侦听器watch 侦听器 计算属性 方法的区别
计算属性和方法的区别: 计算属性有缓存 调用多次只执行一次 方法调用多次就执行多次 侦听器有缓存 computed生成一个新的数据,直接渲染至视图中,watch是修改本身已经存在的数据
界面
<div id ="app" > <h1 > 全名:{{fullname}}</h1 > </div >
js
var app=new Vue ({ el :"#app" , data : { firstname : "bill" , lastname : "盖字" , }, watch : { firstname :function (val ){ this .fullname =val+this .lastname ; }, lastname :function (val ){ this .fullname =this .firstname +val; } }, computed :{ fullname :function ( ){ return this .firstname +this .lastname ; } } });
侦听器 Ajax调用 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="js/vue.js" > </script > <script src ="js/jquery-1.10.2.js" > </script > <style > .pe { color :pink; } .re { color :red; } </style > </head > <body > <div id ="app" > <input type ="text" placeholder ="请输入名字" v-model.lazy ="usname" /> <span :class ="c1" > {{tip}}</span > </div > </body > <script > var app=new Vue ({ el :'#app' , data : { usname :'' , tip :'' , c1 :'' }, watch :{ usname :function (val ){ this .tip ="正在验证..." this .checkName (val); } }, methods :{ checkName :function (value ){ setTimeout (function ( ){ if (value=="admin" ){ app.c1 ="re" ; app.tip ="名字不合法!" ; }else { app.c1 ="pe" ; app.tip ="名字合法!" ; } },2000 ) } } }); </script > </html >
过滤器 | 隔开使用
//过滤器 处理插值表达式和属性
//1、可以用于插值表达式和属性绑定
//2、支持级联操作
全局过滤器 html
<h3 > msg:{{msg | upper}}</h3 >
js
Vue .filter ('upper' ,function (val ){ return val.substring (0 ,1 ).toUpperCase ()+val.substring (1 ).toLowerCase (); })
局部过滤器 var app=new Vue ({ el :'#app' , data : { msg :'' }, watch :{ }, methods :{ }, filters :{ upper2 :function (val ){ return val.substring (0 ,1 ).toUpperCase ()+val.substring (1 ).toLowerCase (); } } });
过滤器带参数 界面
<div id ="app" > <h1 > 原来:{{newtime}}</h1 > <h1 > {{newtime | formattime('yyyy-MM-dd HH:mm:ss')}}</h1 > </div >
js
Vue .filter ('formattime' , function (val,cf ){ if (cf=='yyyy-MM-dd HH:mm:ss' ){ let y=val.getFullYear (); let m=val.getMonth ()+1 ; let d=val.getDate (); let s=val.getHours (); let f=val.getMinutes (); let miao=val.getSeconds (); return `${y} -${m} -${d} ${s} :${f} :${miao} ` ; } }) var app=new Vue ({ el :'#app' , data : { newtime :new Date (), }, watch :{ }, methods :{ } });
生命周期 8个
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="js/vue.js" > </script > <script src ="js/jquery-1.10.2.js" > </script > </head > <body > <div id ="app" > <h1 > 测试 生命周期8个</h1 > <h3 > {{message}}</h3 > <button type ="button" @click ="change" > 改变</button > </div > </body > <script > var app=new Vue ({ el :"#app" , data : { message :'hello vue!' }, methods :{ change : function ( ) { this .message ="hello word!" ; }, change2 ( ){ console .log ("方法也可以这样写!" ); } }, beforeCreate : function ( ) { console .log ("创建前....." ) console .log (this .message ); console .log (this .$el ); }, created ( ){ console .log ("创建完成...." ); console .log (this .message ); console .log (this .$el ); }, beforeMount ( ){ console .log ("挂载前...." ); console .log (this .message ); console .log (this .$el ); }, mounted ( ){ console .log ("挂载完成...." ); console .log (this .message ); console .log (this .$el ); }, beforeUpdate ( ){ console .log ("更新前...." ); console .log (this .message ); console .log (this .$el ); }, updated ( ){ console .log ("更新后...." ); console .log (this .message ); console .log (this .$el ); }, beforeDestroy ( ){ console .log ("销毁前...." ); console .log (this .message ); console .log (this .$el ); }, destroyed ( ){ console .log ("销毁完成...." ); console .log (this .message ); console .log (this .$el ); } }); </script > </html >
数组变化 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="js/vue.js" > </script > <script src ="js/jquery-1.10.2.js" > </script > </head > <body > <div id ="app" > <pre > push 改变原数组 pop 尾部移除 改变原数组 slice 不改变原数组 返回值改变 </pre > <input type ="text" v-model ="mess" > <button type ="button" @click ="add" > 添加</button > <button type ="button" @click ="del" > pop删除</button > <button type ="button" @click ="del2" > splice删除</button > <ul > <li v-for ="item in fruit" > {{item}}</li > </ul > </div > </body > <script > var app=new Vue ({ el :'#app' , data : { mess :'' , fruit :["apple" , "orange" ,"banane" ,"orange2" ,"banane2" ] }, methods :{ add ( ){ this .fruit .push (this .mess ); this .mess ="" ; }, del ( ){ this .fruit .pop (); }, del2 ( ){ this .$set(app.fruit ,1 ,"柠檬" ); } } }); </script > </html >
组件 组件注意事项 1 、data是一个函数2 、组件模板必须是根元素3 、组件的模板内容可以是模板字符串
组件命名注意事项 如果是使用驼峰命名法的组件 在根组件里面无法使用 多个单词只能用- 横杠 驼峰命名法的组件只能在template模板中使用 使用时直接名字 如果组件的名字 有多个单词的时候 如:HelloWord 那么界面组件就是 Hello -Word
全局组件的注册 Vue .component ('button-unter' ,{ data ( ){ return { count :0 } }, template :'<button @click="click">计数 {{ count }} </button>' , methods :{ click ( ){ this .count ++; } } })
使用
<button-unter > </button-unter >
局部组件注册 使用
<Hello-Word > </Hello-Word >
vue
var helloword={ data ( ){ return { name :'张三' } }, template :`<h3>我是{{name}}</h3>` } var app=new Vue ({ el :'#app' , data :{ }, components :{ "hello-word" :helloword } })
父传子组件(传参) 可以传的类型:String number boolean array Object
注意 如果使有样式的话可以直接赋值 或者照下面赋值 示例1 定义样式 .cf { border-bottom : 1px solid red; } 原来赋值 :class ={cf :iscf} 组件赋值::class ="{cf:items.pbool}"
界面
//bolis是自定义的属性名 在组件中接收 title是父元素传的值 <blog2-post :bolis ="title" > </blog2-post >
vue
Vue .component ('blog2-post' ,{ data ( ){ return { postFontSize :16 } }, props :['bolis' ], template :`<div> <div v-for="items in bolis" :class="{cf:items.pbool}"> <h3>标题:{{items.title}}</h3> <p :style="{ fontSize: postFontSize + 'px' }">内容:{{items.context}}</p> <p>内容图片: <img v-for="ite in items.blogimg" :src="ite" width="300px" height="200px" /> </p> <p>博龄:{{items.age+10}}</p> <p>鸣谢: <ul > <li v-for="it in items.help">{{it}}</li> </ul> </p> <p>作者信息: <ul> <li>姓名:{{items.authinfo.name}}</li> <li>创建时间:{{items.authinfo.crtime}}</li> </ul> </p> <button @click="postFontSize+=10">放大字体</button> </div> </div>` }) var app=new Vue ({ el :'#app' , data :{ title :[ { title :"博客1" , context :"博客1内容" , age :19 , pbool :true , help :["auth1" ,"auth9" ,"auth2" ,"auth5" ], authinfo :{name :"auth2" ,crtime :'2021-10-11' }, blogimg :['img/11.webp' ,'img/12.webp' ] }, { title :"博客2" , context :"博客2内容" , age :10 , pbool :true , help :["auth1" ,"auth9" ,"auth2" ,"auth5" ], authinfo :{name :"auth1" ,crtime :'2021-10-11' }, blogimg :['img/11.webp' ] }, { title :"博客3" , context :"博客3内容" , age :15 , pbool :true , help :["auth1" ,"auth9" ,"auth2" ,"auth5" ], authinfo :{name :"auth3" ,crtime :'2021-10-11' }, blogimg :['img/11.webp' ,'img/12.webp' ,'img/22.webp' ] }, { title :"博客4" , context :"博客3内容" , age :20 , pbool :true , help :["auth1" ,"auth9" ,"auth2" ,"auth5" ], authinfo :{name :"auth4" ,crtime :'2021-10-11' }, blogimg :['img/11.webp' ,'img/12.webp' ,'img/22.webp' ,'img/3210.webp' ] } ] } })
效果 实际上就是循环了多个博客
子传父组件 $emit(‘自定义名字’,值) 这个自定义名字需要在使用组件时组成@自定义名字=“方法名”
方法是父类的方法 值是需要传递的值
子组件调用事件通知父组件 1 、子组件模板绑定事件$emit('.....' )2 、子元素标签绑定对应的事件,事件名与$emit括号内的名称一样3 、最后在vue对象中添加方法执行对应的操作 子组件传值 this .$emit('bigtext' ,10 )父组件接收子组件的值 handler (num ){ this .fons +=10 ; console .log ("调用!" +num); }
界面
<menu-item :he ="help" @bigtext ="handler" > </menu-item >
组件
Vue .component ('menu-item' ,{ data ( ){ return { } }, props :['he' ], template :` <div > <ul> <li v-for="item in he">{{item}}</li> </ul> <button @click="test">改变</button> </div> ` , methods :{ test ( ){ this .$emit('bigtext' ); this .$emit('bigtext' ,10 ) } } }) var app=new Vue ({ el :"#app" , data : { help :["auth1" ,"auth9" ,"auth2" ,"auth5" ], pmsg :'父组件' , fons :16 }, methods :{ handler (num ){ this .fons +=10 ; console .log ("调用!" +num); } } });
兄弟组件传值 兄弟之间传值 创建中央处路由 var hub=new Vue (); 通知相对的组件jerry-event :是兄弟的挂载完成的name hub.$emit("jerry-event" ,2 ) 自己挂载完成后监听自己的 mounted ( ){ hub.$on("tom-event" ,(value )=> { this .num +=value; }) }
界面
<tom-com > </tom-com > <jerry-com > </jerry-com >
vue
var hub=new Vue (); Vue .component ("tom-com" ,{ data ( ){ return { num :0 } }, template :` <div> <h3>tom={{num}}</h3> <button type="button" @click="changjerr">改Jerry</button> </div> ` , methods : { changjerr ( ){ hub.$emit("jerry-event" ,2 ) } }, mounted ( ){ hub.$on("tom-event" ,(value )=> { this .num +=value; }) } }) Vue .component ("jerry-com" ,{ data ( ){ return { num :0 } }, template :` <div> <h3>jerry={{num}}</h3> <button type="button" @click="changtom">改Tom</button> </div> ` , methods : { changtom ( ){ hub.$emit("tom-event" ,3 ) } }, mounted ( ){ hub.$on("jerry-event" ,(value )=> { this .num +=value; }) } }) var app=new Vue ({ el :'#app' , data : { } });
插槽 //插槽===>父向子传网页内容 可以传任何东西 然后会替换到slot
//默认消息 组件网页没有传值的话就是slot的默认值
界面
<alter-box > </alter-box > <alter-box > 查询失败!</alter-box > <alter-box > 查询失败! <img src ="img/12.webp" width ="400px" height ="200px" /> <button > 点击</button > </alter-box >
vue
Vue .component ('alter-box' ,{ data ( ){ return { } }, template :`<div id="d1"> <h1>错误消息</h1> <slot >默认消息</slot> </div>` , }) var app=new Vue ({ el :"#app" , data :{ } });
具名插槽(可以起名字) 通过名字指定显示的内容
界面
<base-layout > <div slot ="header" id ="header" > 头部</div > <div slot ="main" id ="main" > 中部</div > <div slot ="footer" id ="footer" > 尾部</div > </base-layout > <base-layout > <template slot ="header" > <h1 > 头部</h1 > <img src ="img/11.webp" width ="400px" height ="200px" /> </template > <template slot ="main" > <h1 > 中部</h1 > <img src ="img/12.webp" width ="400px" height ="200px" /> </template > <template slot ="footer" > <h1 > 尾部</h1 > <img src ="img/22.webp" width ="400px" height ="200px" /> </template > </base-layout >
vue
Vue .component ("base-layout" ,{ data ( ){ return { } }, template :`<div> <header> <slot name="header"></slot> </header> <main> <slot name="main"></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>` , }) var app=new Vue ({ el :'#app' , data :{ } });
效果
作用域插槽 v-slot==slot-scope
子组件传值给父组件
示例1 界面
<div id ="app" > <son-com > <template v-slot ="slotProps" > <h1 > 这是父组件的元素</h1 > <h1 > 子组件元素变量:{{slotProps.user.name}}</h1 > <h1 > 子组件元素变量:{{slotProps.user.nickname}}</h1 > </template > </son-com > </div >
vue
<script> Vue .component ("son-com" ,{ data ( ){ return { heros :{ name :"李白" , nickname :"剑仙" } } }, template :`<div> <h1>作用域插槽</h1> <slot :user="heros"></slot> </div>` , }) var app=new Vue ({ el :"#app" , data : { } }); </script>
示例2 界面
<my-list title ="形状列表" :items ="shapes" > <template v-slot:default ="slotProps" > <div > {{slotProps.item.name}} <small > (sides:{{slotProps.item.sides}})</small > </div > </template > </my-list > <my-list title ="颜色" :items ="color" > <template v-slot:default ="slotProps" > <div > <span class ="swatch" :style ="{backgroundColor:slotProps.item.hex}" > </span > {{slotProps.item.name}}</div > </template > </my-list > <my-list title ="英雄列表" :items ="heros" > <template v-slot:default ="slotProps" > <div > {{slotProps.item.name}} <img width ="40px" height ="40px" :src ="'img/'+slotProps.item.img" /> {{slotProps.item.sex}}</div > </template > </my-list >
vue
<script> Vue .component ("my-list" ,{ data ( ){ return { } }, props :['title' , 'items' ], template :`<div class="my-list"> <div class="title">{{title}}</div> <div class="list"> <div class="list-item" v-for="item in items"> <slot :item="item"></slot> </div> </div> </div>` , }) var app=new Vue ({ el :"#app" , data : { shapes :[ {name :'正方形' ,sides :4 }, {name :'三角形' ,sides :3 }, {name :'六边形' ,sides :6 } ], color :[ {name :'黄色' ,hex :'#FD403F' }, {name :'绿色' ,hex :'#229954' }, {name :'粉色' ,hex :'#9B59B6' } ], heros :[ {name :'temo' ,img :'11.webp' ,sex :'男' }, {name :'德玛' ,img :'12.webp' ,sex :'男' }, {name :'女警' ,img :'22.webp' ,sex :'女' } ] } }); </script>
效果
路由 路由需要先引用vue 在引用路由
可以不用挂载组件
下载路由
npm i vue-router@3.0 .2 然后拷贝js
原生模拟路由 <component :is ="comname" > </component > <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <a href ="#/cj" > 财经</a > <a href ="#/ty" > 体育</a > <a href ="#/xw" > 新闻</a > <a href ="#/js" > 军事</a > <hr > <component :is ="comname" > </component > </div > </body > <script > var cj={ template :`<h1>财经</h1>` } var ty={ template :`<h1>体育</h1>` } var xw={ template :`<h1>新闻</h1>` } var js={ template :`<h1>军事</h1>` } Vue .component ('' ,{ }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, components :{ cj,ty,xw,js } }) window .onhashchange = function ( ){ let path=location.hash .substring (1 ); console .log (path); switch (path) { case "/cj" : app.comname =cj; break ; case "/ty" : app.comname =ty; break ; case "/xw" : app.comname =xw break ; case "/js" : app.comname =js break ; } } </script > </html >
路由基本使用 <router-link to ="/cj" > 财经</router-link > <router-view > </router-view > <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <router-link to ="/cj" > 财经</router-link > <router-link to ="/ty" > 体育</router-link > <router-link to ="/xw" > 新闻</router-link > <router-link to ="/js" > 军事</router-link > <a href ="#/cj" > 财经</a > <a href ="#/ty" > 体育</a > <a href ="#/xw" > 新闻</a > <a href ="#/js" > 军事</a > <hr > <router-view > </router-view > </div > </body > <script > var cj={ template :`<h1>财经</h1>` } var ty={ template :`<h1>体育</h1>` } var xw={ template :`<h1>新闻</h1>` } var js={ template :`<h1>军事</h1>` } var router=new VueRouter ({ routes :[ {path :"/cj" ,component :cj}, {path :"/ty" ,component :ty}, {path :"/xw" ,component :xw}, {path :"/js" ,component :js}, ] }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, components :{ cj,ty,xw,js }, router :router }) </script > </html >
路由重定向 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <router-link to ="/cj" > 财经</router-link > <router-link to ="/ty" > 体育</router-link > <router-link to ="/xw" > 新闻</router-link > <router-link to ="/js" > 军事</router-link > <a href ="#/cj" > 财经</a > <a href ="#/ty" > 体育</a > <a href ="#/xw" > 新闻</a > <a href ="#/js" > 军事</a > <hr > <router-view > </router-view > </div > </body > <script > var cj={ template :`<h1>财经</h1>` } var ty={ template :`<h1>体育</h1>` } var xw={ template :`<h1>新闻</h1>` } var js={ template :`<h1>军事</h1>` } var router=new VueRouter ({ routes :[ {path : "/" ,redirect :'/cj' }, {path :"/cj" ,component :cj}, {path :"/ty" ,component :ty}, {path :"/xw" ,component :xw}, {path :"/js" ,component :js}, ] }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, components :{ cj,ty,xw,js }, router :router }) </script > </html >
嵌套路由 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <router-link to ="/index" > 首页</router-link > <router-link to ="/reg" > 注册</router-link > <hr > <router-view > </router-view > </div > </body > <script > var index={ template :`<h1>主页</h1>` } var regis={ template :`<div> <h1>用注册</h1> <router-link to="/tab1">table1</router-link> <router-link to="/tab2">table2</router-link> <hr> <router-view></router-view> </div>` } var tab1={ template :'<h1>表格1</h1>' } var tab2={ template :'<h1>表格2</h1>' } var router=new VueRouter ({ routes :[ {path : "/" ,redirect :'/index' }, {path :"/index" ,component :index}, {path :"/reg" ,component :regis, children :[ {path : '/tab1' ,component :tab1 }, {path : '/tab2' ,component :tab2 }, ]} ] }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, router :router }) </script > </html >
动态路由传值 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <router-link to ="/index/1" > 首页</router-link > <router-link to ="/index/2" > 首页</router-link > <router-link to ="/reg" > 注册</router-link > <hr > <router-view > </router-view > </div > </body > <script > var index={ template :`<h1>{{$route.params.id}}主页</h1>` } var regis={ template :`<div> <h1>用注册</h1> </div>` } var router=new VueRouter ({ routes :[ {path : "/" ,redirect :'/index/:id' }, {path :"/index/:id" ,component :index}, {path :"/reg" ,component :regis} ] }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, router :router }) </script > </html >
动态路由传值2 需要传值时 在规则中加 props:true
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > a { margin-right : 10px ; text-decoration : none; } </style > </head > <body > <div id ="app" > <router-link to ="/index/1" > 首页</router-link > <router-link to ="/index/2" > 首页</router-link > <router-link to ="/reg/temo/pd" > 注册</router-link > <router-link to ="/reg2" > 注册2</router-link > <router-link to ="/reg3/18" > 注册2</router-link > <hr > <router-view > </router-view > </div > </body > <script > var index={ props :['id' ], template :`<h1>{{id}}主页</h1>` } var regis={ props :['name' ,'kn' ], template :`<div> <h1>用注册{{name}} {{kn}}</h1> </div>` } var regis2={ props :['age' ,'sex' ], template :`<div> <h1>用注册{{age}} {{sex}}</h1> </div>` } var regis3={ props :['age' ,'sex' ,'id' ], template :`<div> <h1>用注册{{age}} {{sex}} {{id}}</h1> </div>` } var router=new VueRouter ({ routes :[ {path : "/" ,redirect :'/index/1' }, {path :"/index/:id" ,component :index,props :true }, {path :"/reg/:name/:kn" ,component :regis,props :true }, {path :"/reg2" ,component :regis2,props : { age :19 , sex :'男' }}, {path :"/reg3/:id" ,component :regis3,props :router => ({ age :19 , sex : '男' , id :router.params .id })}, ] }) var app=new Vue ({ el :"#app" , data :{ comname :'' }, router :router }) </script > </html >
路由传值3 <router-link :to ="`/home?text=${text}`" > 首页</router-link >
对象
<router-link :to ="{ path: '/home', query: { text: text } }" > 首页</router-link >
获取
{ name : 'shouye' , path : 'home/:text' ,
字符串
<router-link :to ="`/home${text}`" > 首页</router-link >
对象
<router-link :to ="{ name: 'shouye', params: { text: text } }" > 首页</router-link >
获取
* 注意
* 字符串形式传参时需加占位符告知路由器, 在路径后面是参数
* path对应的是 query属性,name 对应的是 params 属性
this .$router .push ({ path : "/home" , query : { text : this .text , },});
导航到新路由 this .$router .push ("/userinfo" );
返回上一步回退 后台管理示例 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <script src ="js/vue.js" > </script > <script src ="js/vue-router.js" > </script > <style > .d1 { position : absolute; width : 947px ; height : 500px ; background : #FFFFFF ; border : 1px solid black; } header { height : 50px ; background-color : #545c64 ; line-height : 50px ; text-align : center; font-size : 24px ; color : #fff ; } footer { height : 40px ; line-height : 40px ; background-color : #888 ; position : absolute; bottom : 0 ; width : 100% ; text-align : center; color : #fff ; } #d2 { height : 410px ; width : 100% ; background-color :#545C63 ; } ul { margin : 0 ; padding : 0 ; list-style : none; } ul li { height : 45px ; line-height : 45px ; background-color : #a0a0a0 ; color : #fff ; text-align : center; border-bottom : 1px solid #fff ; } #d3 { float : left; width :150px ; height :100% ; } #main { float :left ; width :797px ; height :100% ; text-align : center; background-color : white; } table { width : 789px ; border-collapse : collapse; margin-left : 4px ; margin-right : 4px ; overflow :hidden;white-space :nowrap; } th { background-color : #ddd ; } td , th { border : 1px solid #eee ; line-height : 35px ; font-size : 12px ; } ul a { text-decoration : none; color : #F2F2F2 } button { height : 30px ; background-color : #ecf5ff ; border : 1px solid lightskyblue; font-size : 12px ; padding : 0 20px ; } </style > </head > <body > <div id ="app" > <router-view > </router-view > </div > </body > <script > var main={ template:`<div class ="d1" > <header > 后台管理系统 </header > <div id ="d2" > <div id ="d3" > <ul > <li > <router-link to ="/user" > 用户管理</router-link > </li > <li > <router-link to ="/jur" > 权限管理</router-link > </li > <li > <router-link to ="/shop" > 商品管理</router-link > </li > <li > <router-link to ="/order" > 订单管理</router-link > </li > <li > <router-link to ="/sys" > 系统设置</router-link > </li > </ul > </div > <router-view > </router-view > </div > <footer > 版权所有 </footer > </div > `, } var user={ data(){ return{ userli:[ {id:1,name:'张三',age:10}, {id:2,name:'李四',age:20}, {id:3,name:'王五',age:30}, {id:4,name:'赵柳',age:40} ] } }, template: `<div id ="main" > <h1 > 用户管理</h1 > <table > <tr > <th > 编号</th > <th > 姓名</th > <th > 年龄</th > <th > 操作</th > </tr > <tr v-for ="lis in userli" > <td > {{lis.id }} </td > <td > {{lis.name }} </td > <td > {{lis.age }} </td > <td > <a href ="#" @click.prevent ="ope(lis.id)" > 操作</a > </td > </tr > </table > </div > `, methods:{ ope(id){ this.$router.push("/userinfo/" + id) } } } var userinfo ={ props:['id'], template: `<div id ="main" > <h1 > 用户ID: {{id }} </h1 > <button @click ="repre" > 后退</button > </div > `, methods:{ repre(){ this.$router.go(-1); } } } var jur={ template: `<div id ="main" > <h1 > 权限管理</h1 > </div > ` }; var shop={ template: `<div id ="main" > <h1 > 商品管理</h1 > </div > ` }; var order={ template: `<div id ="main" > <h1 > 订单管理</h1 > </div > ` }; var sys={ template: `<div id ="main" > <h1 > 系统设置</h1 > </div > ` }; var router=new VueRouter({ routes:[ //先打开一个组件 然后重定向到user {path:"/",component:main,redirect:'/user', children:[ {path:"/user",component:user}, {path:"/userinfo/:id",component:userinfo,props:true}, {path:"/jur",component:jur}, {path:"/shop",component:shop}, {path:"/order",component:order}, {path:"/sys",component:sys} ]}, ] }) var app=new Vue({ el:"#app", data: { }, router }) </script > </html >
命名路由 界面
//name:'路由规则里面调用的' <router-link to ="/user/88" > 用户</router-link > <router-link :to ="{name:'yh',params:{ id:19 }}" > 用户</router-link > <router-link to ="/reg" > 注册</router-link > <router-view > </router-view >
路由规则添加命名
var router=new VueRouter ({ routes :[ {path :'/' ,redirect :'/user/:id' }, {name : 'yh' ,path :'/user/:id' ,component :User ,props :true }, {path :'/reg' ,component :reg}, ] })
传值
<router-link :to="{name:'yh',params:{ id:19 }}" >用户</router-link>props :['id' ]
编程式导航 跳转 var User ={ props :['id' ], template :`<div> <h1>用户组件 {{id}}</h1> <button @click="add">添加</button> </div>` , methods :{ add ( ){ this .$router .push ('/reg' ); } } }
跳转传值 var reg={ template :`<div> <h1>用户注册</h1> <button @click="gouser">去用户</button> </div>` , methods :{ gouser ( ){ this .$router .push ({ name : 'yh' , params : { id :109 } }) } } } 获取值 props :['id' ]
回退 Vue脚手架 使用UI创建项目 安装脚手架
查看版本
使用UI
选择路径创建项目
选择预设 手动
选择功能 Babel(优化高版本代码浏览器不兼容)、Router(路由)、Linter/Formatter(代码规范)、使用配置文件
选择版本 语法检查+标准配置
生成的项目结构
使用命令创建项目 如果安装了脚手架的情况下就执行下面操作
创建项目
//在需要创建项目的目录下输入shell命令 vue create 名字
选择对应的内容 上下选择 空格选中
运行项目
启动UI界面 去掉语法规范 vue.config.js
Vue项目目录说明 + Vuecli01 + node_modules(存放第三方模块) + public(存放静态文件) - favicon.ico (图标) - index.html (页面模板) + src(我们自己写的文件一般放在这个文件夹下) + assets(存放资源文件 图片) + components(存放公共组件) + router(存放路由) + views(存放视图组件) - App .vue (页面入口文件) - main.js (程序入口文件) .$mount ==el :'#app' 项目入口 @是/src的别名 src/App .vue 根组件单文件 三部分 template、script、style 安装 Vetur vscode插件
示例 创建一个 /views/UserView.vue
<template > <div > <h1 > V㛑 goods</h1 > <img alt ="goods" src ="../assets/3210.webp" > </div > </template > <script > export default { name : 'UserView' } </script > <style > img { width : 600px ; height : 400px ; } </style >
添加路由 router/index.js
{ path : '/user' , name : 'user' , component : UserView }
效果
修改项目运行的端口 vue.config.js
const { defineConfig } = require ('@vue/cli-service' )module .exports = defineConfig ({ transpileDependencies : true , lintOnSave :false , devServer :{ open : true , port :8090 } })
使用命令下载Element UI npm下载
main.js下面 引入element ui
import ElementUI from 'element-ui' ;import 'element-ui/lib/theme-chalk/index.css' ;Vue .use (ElementUI );
示例table使用
<template > <div > <el-table :data ="tableData" style ="width: 100%" :row-class-name ="tableRowClassName" > <el-table-column prop ="date" label ="日期" width ="180" > </el-table-column > <el-table-column prop ="name" label ="姓名" width ="180" > </el-table-column > <el-table-column prop ="address" label ="地址" > </el-table-column > </el-table > </div > </template > <script > export default { name : "TableView" , methods :{ tableRowClassName ({row, rowIndex} ) { if (rowIndex === 1 ) { return 'warning-row' ; } else if (rowIndex === 3 ) { return 'success-row' ; } return '' ; } }, data ( ){ return { tableData :[ {date :'2021-10-11' ,name :'张三' ,address :'上海市普陀区金沙江路 1518 弄' }, {date :'2021-10-17' ,name :'张三' ,address :'上海市普陀区金沙江路 1518 弄' }, {date :'2021-10-14' ,name :'张三' ,address :'上海市普陀区金沙江路 1518 弄' }, {date :'2021-10-13' ,name :'张三' ,address :'上海市普陀区金沙江路 1518 弄' }, {date :'2021-10-12' ,name :'张三' ,address :'上海市普陀区金沙江路 1518 弄' } ] } } } </script > <style > .el-table .warning-row { background : oldlace; } .el-table .success-row { background : #f0f9eb ; } </style >
使用UI下载Element UI插件 这里下载的插件属于按需引入需要什么引入什么
选择好项目 选择插件 添加插件 搜索element ui 选中点安装
配置插件
安装后会多一个文件夹 src/plugins 下面有element.js
在element.js下按需引入
import Vue from 'vue' import {Button , Table , TableColumn } from 'element-ui' Vue .use (Button )Vue .use (Table )Vue .use (TableColumn )
使用示例
<template > <div > <el-table :data ="tableData" style ="width: 100%" :row-class-name ="tableRowClassName" > <el-table-column prop ="date" label ="日期" width ="180" > </el-table-column > <el-table-column prop ="name" label ="姓名" width ="180" > </el-table-column > <el-table-column prop ="address" label ="地址" > </el-table-column > </el-table > </div > </template > <script > export default { name : "TableView" , methods : { tableRowClassName ({row, rowIndex} ) { if (rowIndex === 1 ) { return 'warning-row' ; } else if (rowIndex === 3 ) { return 'success-row' ; } return '' ; } }, data ( ) { return { tableData : [{ date : '2016-05-02' , name : '王小虎' , address : '上海市普陀区金沙江路 1518 弄' , }, { date : '2016-05-04' , name : '王小虎' , address : '上海市普陀区金沙江路 1518 弄' }, { date : '2016-05-01' , name : '王小虎' , address : '上海市普陀区金沙江路 1518 弄' , }, { date : '2016-05-03' , name : '王小虎' , address : '上海市普陀区金沙江路 1518 弄' }] } } } </script > <style > .el-table .warning-row { background : oldlace; } .el-table .success-row { background : #f0f9eb ; } </style >
注意 下面这种情况是因为没有引入需要的内容
Element UI 表单使用 安装less
//安装less npm install less less-loader@7.0.0 -D <template > <div class ="login_co" > <div class ="content" > <div class ="content_input" > <div class ="title" > <p > 管理员登录</p > </div > <el-form :model ="ruleForm" status-icon :rules ="rules" ref ="ruleForm" > <el-form-item prop ="username" > <el-input type ="text" clearable v-model ="ruleForm.username" autocomplete ="off" placeholder ="用户名" > </el-input > </el-form-item > <el-form-item prop ="password" > <el-input type ="password" clearable show-password v-model ="ruleForm.password" autocomplete ="off" placeholder ="密码" > </el-input > </el-form-item > <div class ="content_button" > <el-button type ="primary" @click ="login" > 登录</el-button > <el-button @click ="replace" > 重置</el-button > </div > </el-form > </div > </div > </div > </template > <script > import '@/assets/css/style.css' import '@/assets/js/ribbon.js' export default { name : "Login" , data ( ){ return { ruleForm : { username : '' , password :'' , }, rules : { username : [ {required : true , message : '请输入用户名' , trigger : 'blur' }, ], password :[ {required : true , message : '请输入密码' , trigger : 'blur' }, ] } } }, methods :{ login ( ){ this .$refs .ruleForm .validate (async (valid) => { if (valid!=true ){ this .$message({ showClose : true , message : '请检查账号密码!' , type : 'warning' }); return ; }else { let ret=await this .$http .post ('login' ,this .ruleForm ); console .log (ret.data .token ); } }) }, replace ( ){ this .$refs .ruleForm .resetFields (); } } } </script > <style lang ="less" scoped > .login_co { //background-color :#2b4b6b ; height :100% ; } </style > main.js import '@/assets/css/global.css' import axios from 'axios' //axios挂Vue Vue.prototype.$http =axios; axios.defaults.baseURL="http://47.101.177.78:8888/api/private/v1/" //拦截器 axios.interceptors.response.use(function (res){ return res.data; })
导入全局样式 在main.js下面导入
import '@/assets/css/global.css'
局部组件导入样式 在组件<script></script>
里面导入
下载挂载axios import axios from 'axios' Vue .prototype .$http =axios;axios.defaults .baseURL ="http://47.101.177.78:8888/api/private/v1/"
路由守卫 方法1 router/index.js router导出 router.beforeEach ((to,from ,next )=> { if (to.path =='/login' ){ next (); }else if (sessionStorage.getItem ('token' )==null ){ next ({path :'/login' }) }else { next (); } })
方法2 路由配置 meta需要鉴权 isauth随便定义的name 需要拦截的地方
{ path : 'front' , component : Front , meta : { isAuth : true }, }, { path : 'back' , component : Back , meta : { isAuth : true }, }, router.beforeEach ((to, from , next ) => { if (to.meta .isAuth ) { if (localStorage .getItem ('isShow' === '1' )) { next (); } else { alert ('暂无权限观看' ); } } else { next (); } });
设置Token axios.interceptors .request .use (function (res ){ let token=sessionStorage.getItem ('token' ); res.headers .Authorization =token; return res; })
Keep-alive 组件缓存 //注意 Front 是组件的名字 <keep-alive include ="Front" > <router-view > </router-view > </keep-alive >
Vuex getter state里面的只能在计算属性中解析
compued :{ ...mapGetters ('模块名' ,['变量名 || 方法名' ]) }
mutations在方法中使用
使用UI创建项目
命令下载vuex
搭建vux运行环境 创建 /store/index.js
文件
import Vue from 'vue' import Vuex from 'vuex' Vue .use (Vuex ) export default new Vuex .Store ({ actions :{}, mutations :{}, state :{}, }) import store from './store/index.js' new Vue ({ el :"#app" , render : h => h (App ), store :store })
定义组件 AddNumber.vue
<template > <div > <h1 > 当前的计数(+):{{$store.state.count}} -- {{$store.getters.con}}</h1 > <button @click ="add" > 加不传值</button > <button @click ="add2" > 加传值</button > <button @click ="add3" > 异步加N</button > </div > </template > <script > export default { name : "AddNumber" , data ( ){ return { } }, methods :{ add ( ){ this .$store .commit ('add' ); }, add2 ( ){ this .$store .commit ('addn' ,5 ); }, add3 ( ){ this .$store .dispatch ('add3' ,5 ); } } } </script > <style scoped > </style >
SubtractionNumber.vue
<template > <div > <h1 > 当前的计数(-):{{count}}</h1 > <button @click ="hand" > 减不传值</button > <button @click ="hand2" > 减传值</button > <button @click ="hand3" > 异步减传值</button > </div > </template > <script > import {mapState} from 'vuex' import {mapMutations} from 'vuex' import { mapActions } from 'vuex' export default { name : "SubtractionNumber" , data ( ){ return { } }, computed :{ ...mapState (['count' ]) }, methods :{ ...mapMutations (['sub' ,'subn' ]), ...mapActions (['asysubn' ]), hand ( ) { this .sub () }, hand2 ( ){ this .subn (5 ); }, hand3 ( ){ this .asysubn (10 ); } } } </script > <style scoped > </style >
store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue .use (Vuex )export default new Vuex .Store ({ state : { count :0 }, getters : { con (state ){ if (state.count <=0 ){ return state.count =1 }else { return state.count ; } } }, mutations : { add (state ){ state.count ++; }, addn (state,value ){ state.count +=value; }, sub (state ){ state.count --; }, subn (state,val ){ state.count -=val; } }, actions : { add3 (context,value ){ setTimeout (function ( ){ context.commit ('addn' ,value); },3000 ) }, asysubn (context,value ){ setTimeout (function ( ){ context.commit ('subn' ,value); },3000 ) } }, modules : { } })
state获取共享属性 共享属性也就是 strore/index.js下的state下的属性
获取方式一 <h1 > 当前的计数(+):{{$store.state.count}}</h1 >
获取方式二 使用计算属性
先导入 import {mapState} from 'vuex' computed :{ ...mapState (['count' ]) }, <h1 > 当前的计数(-):{{count}}</h1 >
mutations同步修改共享属性 方法一 commit(‘在store/inde.js的 mutations里面定义的方法名’)
methods :{ add ( ){ this .$store .commit ('add' ); }, add2 ( ){ this .$store .commit ('addn' ,5 ); } }
store/index.js
mutations : { add (state ){ state.count ++; }, addn (state,value ){ state.count +=value; } }
方法2 导入 import {mapMutations} from 'vuex' methods :{ ...mapMutations (['sub' ,'subn' ]), hand ( ) { this .sub () }, hand2 ( ){ this .subn (5 ); } }
store/index.js
mutations : { sub (state ){ state.count --; }, subn (state,val ){ state.count -=val; } }
actions异步修改共享属性 Action 提交的是 mutation,而不是直接变更状态。 Action 可以包含任意异步操作。 注意actions
能够提供 dispatch
方法实现异步操作mutations
必须是同步函数state
只能通过 mutations
配置的方法去修改 方法一 methods :{ add3 ( ){ this .$store .dispatch ('add3' ,5 ); } }
store/index.js
mutations : { addn (state,value ){ state.count +=value; } }, actions : { add3 (context,value ){ setTimeout (function ( ){ context.commit ('addn' ,value); },3000 ) } }
方法二 导入 import { mapActions } from 'vuex' methods :{ ...mapActions (['asysubn' ]), hand3 ( ){ this .asysubn (10 ); } }
store/inde.js
mutations : { subn (state,val ){ state.count -=val; } }, actions : { asysubn (context,value ){ setTimeout (function ( ){ context.commit ('subn' ,value); },3000 ) } },
store的计算属性getters 对 store
中 state
数据进行加工 配置 store/index.js getters : { changeCount (state ) { return state.count * 2 ; }, },
取值
<h1 > 加工后的计数:{{$store.getters.changecount}}</h1 >
多组件共享数据 读取 store
的state中 count
和 list
<ul > <li v-for ="(i, index) in list" :key ="index" > {{ i.name }}</li > </ul > <button @click ="xiajia" > 下架</button > <h1 > 当前计数为:<span > {{ count }}</span > </h1 >
computed : { count ( ) { return this .$store .state .count ; }, list ( ) { return this .$store .state .list ; }, },
操作 store
的state
methods : { xiajia ( ) { this .$store .commit ("XIAJIA" ); }, },
store/index.js
state : { count :0 , list :[ {name : 'HTML' }, {name : 'Java' }, {name : 'C#' } ] }, getters : {}, mutations : { XIANJIAO (state ){ state.list .pop (); } }, actions : { add (context,value ){ setInterval (()=> { context.commit ('ADD' ,value); },1000 ) }, reduce (context,value ){ context.commit ('REDUCT' ,value) } }, modules : {}
模块使用 有许多数据需要共享时 需要进行模块化开发
如创建一个cart.js的模块
export default { namespaced : true , state : () => ({ }), getters : { }, mutations : { } }
store.js需要注册模块
import Vue from 'vue' import Vuex from 'vuex' import carmoudele from './cart.js' Vue .use (Vuex );export default new Vuex .Store ({ modules :{ m_cart :carmoudele } })
使用cart.js模块
import { mapState, mapMutations } from 'vuex' computed : { ...mapState ('m_cart' , ['cart' ]) }
Vue3 vue3的项目创建和vue2是一样的 最后版本选择3即可
项目文件介绍区别 入口文件 main.js
使用 createApp
解析模板,更加小巧 import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' createApp (App ).use (store).use (router).mount ('#app' )
组件 <template>
标签里可以插入多个根标签 setup setup
函数是Vue3新的配置项是使用组合API的前提,数据、方法都要放到setup
函数里声明 写法 setup ( ){ let name = "HelloWordld" ; let age = 18 ; function f ( ) { alert (`你好,我是${name} ,今年${age} ` ); }; return { name, age, f } } <template> <h1 > hello world</h1 > <h1 > 姓名:{{name}}</h1 > <h1 > 年龄:{{age}}</h1 > <button @click ="f" > 打招呼</button > </template>
实现数据的响应式–ref函数 定义 * 定义一个响应式的数据
基本类型数据 * 引入 `ref` 函数
import { ref } from "vue"
* 创建一个包含响应式数据的引用对象( `ref` 对象)
let name = ref ("张三" ); let age = ref (18 );
操作数据
function changePerson ( ) { name.value = "李四" ; age.value = "19" ; }
对象类型数据 创建一个包含响应式数据的引用对象( ref
对象)
let obj=ref ({ id :10 , name :'农科' })
操作数据
function ChangeObject ( ){ obj.value .id =228 ; obj.value .name ='王华' }
注意 * 可以处理基本类型数据、数组或者对象类型的数据
* 基本类型数据的响应式是通过 `Object.defineProperty()` 实现
* 对象类型数据的响应式是通过 ES6 中的 `Proxy` 实现
实现数据的响应–reactive 可以把所有的定义到一个变量里面
定义定义一个对象类型
的响应式数据(不能处理基本类型数据) 写法 对象 let obj=reactive ({ id :10 , name : "李四" , age :90 }); function objchnage ( ){ obj.name ='王五' };
数组
let nk=['苹果' ,'香蕉' ,'西瓜' ,'葡萄' ];function objchnage ( ){ nk[1 ]='西瓜2' ; };
reactive
和 ref
不同点处理数据类型不同: ref
可以处理基本类型和对象(数组)类型数据,reactive
只能处理对象(数组)类型数据 实现原理不同:ref
处理基本类型数据通过 Object.defineProperty()
实现,reactive
通过 Proxy
实现 操作不同:ref
操作数据需要加 .value
组件数据多时更加趋向使用 reactive
setup执行事件 和 2个参数 简介:详解setup函数的两个参数
执行时机在生命周期函数 beforeCreate
之前执行一次,而且 setup
函数没有 this
两个参数 export default { props : ["mess" ], setup (props ) { console .log (props.mess ); }, };
* context
* 上下文对象
触发自定义事件
export default { emits : ["xd" ], setup (props, context ) { function clickMe ( ) { context.emit ("xd" , "子组件的值" ); } return { clickMe, }; }, };
setup中的计算属性 定义通过已有的属性计算而来,跟vue2.x中的功能原理一样,使用方式有区别 使用 计算 ref
定义的响应式数据 const fullName = computed ({ get ( ) { return firstName.value + "-" + lastName.value ; }, set (value ) { const arr = value.split ("-" ); firstName.value = arr[0 ]; lastName.value = arr[1 ]; }, });
计算reactive定义的响应式数据
person.fullName = computed ({ get ( ) { return person.firstName + "-" + person.lastName ; }, set (value ) { const arr = value.split ("-" ); person.firstName = arr[0 ]; person.lastName = arr[1 ]; }, });
setup中的侦听器 ref侦听 定义监听值的变化,执行相关的操作,跟vue2.x中的配置一样 监听 ref
定义的数据 watch (num, (newValue, oldValue ) => { console .log ("num增加了" , newValue, oldValue); },{ immediate : true , deep : true }); watch ([num, num1], (newValue, oldValue ) => { console .log ("num增加了" , newValue, oldValue); });
reactive侦听 watch (numObj, (newValue, oldValue ) => { console .log ("numObj变化了" , newValue, oldValue);});
监听对象中的一个基本类型属性
watch ( () => numObj.a , (newValue, oldValue ) => { console .log ("numObj变化了" , newValue, oldValue); });
监听对象中的一些基本类型属性
watch ([() => numObj.a , () => numObj.b ], (newValue, oldValue ) => { console .log ("numObj变化了" , newValue, oldValue);});
监听对象中的对象类型属性
watch ( numObj.c , (newValue, oldValue ) => { console .log ("numObj.c变化了" , newValue, oldValue); } );
总结实现监听生效ref
定义的数据基本类型数据作为监听值 对象作为监听值,需要加 .value
(用的少) reactive
定义的数据 注意如果监听 reactive
定义的对象,则无法正确输出 oldValue
,且深度监听是强制开启的,无法关闭 (vue3配置) setup中的watchEffect函数 定义在监听的回调函数中使用了属性,则监听该属性,不用在参数上指明监听哪个属性 写法 watchEffect (() => { let xd = numa.value ; let xd1 = numb.value ; console .log ("watchEffect函数执行了" );
});与 watch
的区别属性监听区别:watch
手动添加定向的监听属性watchEffect
自动监听使用到的属性 初始化执行: 建议开发中使用 watch
监听,逻辑简单、依赖属性少的场景可以使用 watchEffect
toRef和toRefs函数 toRef定义创建一个 ref
对象,其 value
值指向另一个对象中指定的属性 写法 const name = toRef (person, "name" );
* 作用
* 将某个响应式对象的某一个属性提供给外部使用
toRefs定义批量创建多个 ref
对象,其 value
值指向另一个对象中指定的属性 写法 setup ( ) { let person = reactive ({ name : "张三" , age : 19 , }); return { ...toRefs (person), }; }
* 作用
* 将某个响应式对象的全部属性提供给外部使用
给src属性赋值是图片无法显示 图片位置
赋值时
图表init错误 import * as echarts from 'echarts'
使用mavonEditor编辑器 下载依赖
npm install mavon-editor --save
main.js引入
import mavonEditor from 'mavon-editor' import 'mavon-editor/dist/css/index.css' Vue .use (mavonEditor)
使用组件
<mavon-editor v-model="article.article_content_md" style="height: 100%;" ref=md @save="saveArticles" @imgAdd="$imgAdd" fontSize="16px" > <button type ="button" class ="op-icon el-icon-document" :title ="'摘要/封面'" slot ="left-toolbar-after" @click ="dialogVisible = true" > </button > </mavon-editor>
上传图片
$imgAdd(pos, $file){ var formdata = new FormData (); formdata.append ('headimg' , $file); this .$axios({ url : 'http://127.0.0.1:3000/api/article/img/upimg' , method : 'post' , data : formdata, headers : { 'Content-Type' : 'multipart/form-data' }, }).then ((res )=> { console .log (res); this .$refs .md .$img2Url(pos, res.data .data ); }) },
vue组件导入css
@import "../assets/css/cropper.css" ;
全局过滤 main.js
Vue .filter ("create_time" , function (value ) { return moment (value).format ("yyyy-MM-DD HH:mm:ss" ); });
使用
<template v-slot="scope"> {{scope.row.create_time | create_time}} </template>
Vue项目打包 项目下运行 生成dist文件
上传到服务器
scp dist.zip root@IP :/存放地址
下载启动依赖
找到dist的路径 执行
nginx打包
一样的先build 上传dist文件夹
https://www.runoob.com/linux/nginx-install-setup.html
修改nginx配置文件即可
创建vueTS(typescript)项目 命令
ui
解决element ui aside高度跟不上其他地方的 //设置样式高为height就行
data ( ){ return { menuHeight : { height : "" } } }, created ( ) { var docHeight = document .body .scrollHeight ; this .menuHeight .height = docHeight - 20 + "px" ; console .log (this .menuHeight .height , "this.containerHeight.height" ); }
样式穿透 >>> .autose >>> input { position : absolute; }
/deep/ .wrapper /deep/ .swiper-pagination-bullet-active { background : #fff ; }
slot获取序号 <template slot-scope ="scope" > <span style ="margin-left: 10px" > {{ scope.$index+1 }}</span > </template >
vue3+vite+ts无法识别App.vue 修改env.d.ts
文件
declare module "*.vue" { import { DefineComponent } from "vue" const component : DefineComponent <{}, {}, any > export default component }
main.ts
import App from './App.vue' ;