Vue
MVVM的思想
Ajax请求数据
- 点击按钮出发事件
- 使用$.post $.get $.ajax 发请求
- 请求 完成之后拿到数据
- 使用document.getElementById(“id”)找到页面的dom对象
- 把第三部请求回来的数据使用innrText innerHtml去修改
MVVM设计思想
MVC
|–M Model (domain,service,serviceimpl.utils.pojo.mapper****)
|–V view thymeleaf jsp html
|–C controller **接收前端请求(**控制器)
Model:对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在模型层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。个人理解:后端提供API,后端服务架构是 控制器+数据模型 或者 纯控制器。
View:View是作为视图模板,用于定义结构、布局。它自己不处理数据,只是将ViewModel中的数据展现出来。此外为了和ViewModel产生关联,那么还需要做的就是数据绑定的声明,指令的声明,事件绑定的声明。ViewModel和View之间是双向绑定,意思就是说ViewModel的变化能够反映到View中,View的变化也能够改变ViewModel的数据值。
ViewModel:ViewModel起着连接View和Model的作用,同时用于处理View中的逻辑。在MVC框架中,视图模型通过调用模型中的方法与模型进行交互,然而在MVVM中View和Model并没有直接的关系,在MVVM中,ViewModel从Model获取数据,然后应用到View中。个人理解:Web前端的webserver对View进行双向绑定渲染。
整个MVVM实际上实现了前后端分离,通过api来实现前后端交互,前端通过纯js或者双向绑定框架来渲染页面。
前后端不分离(crm页面写在crm项目里面 html thymeleaf(模板引擎) )
前后端分离
大概如:
数据库(MySQL、PostgreSQL)<—双向交互—>api(php、java、Python、node)<—双向交互—>ajax/fetch/websocket(node服务、jQ、js)<—双向绑定—>html(标签、css)。
MVVM有利于项目分工和升级,所谓对前后端分离。但也有缺点,就是不利于 。
MVC:服务端来渲染数据,老旧模式。MC属于纯后端,V属于前端,js权重不高,有利于SEO。
万物基于api,一套api可以针对小程序、app、前端,为何不首先使用。需要SEO对部分,单独分离出项目,采用MVC渲染静态页面或者纯html即可。
MVVM图例解析
如下图:
v-text,v-html,v-pre,v-once指令
概述
- Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
- 在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
v-text
v-text主要用来更新textContent,可以等同于JS的innerText属性。
<span v-text="msg"></span>
这两者等价:
<span>{{msg}}</span>
v-html
双大括号的方式会将数据解释为纯文本,而非HTML。为了输出真正的HTML,可以用v-html指令。它等同于JS的innerHtml属性。
或者jquery的$().html(aaa)
<div v-html="rawHtml"></div>
这个div的内容将会替换成属性值rawHtml,直接作为HTML进行渲染。
v-pre
v-pre主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。
<div id="app"> <span v-pre>{{message}}</span> //这条语句不进行编译 <span>{{message}}</span> </div>
最终仅显示第二个span的内容
v-once
v-once关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。
<span v-once>This will never change:{{msg}}</span> //单个元素 <div v-once>//有子元素 <h1>comment</h1> <p>{{msg}}</p> </div>
上面的例子中,msg即使产生改变,也不会重新渲染。
练习
<!DOCTYPE html> <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <!--必须 要有一个根标签 必须给一个 id 属性--> <div id="app"> v-text 指令: 相当于html innerText<br/> <span v-text="text"></span> <br/> {{text}} <br/> <span>{{text}}</span> <br/> <br/><br/><br/> v-html 指令:相当于 html innerHtml<br/> <span v-html="html"></span> <br/> <br/><br/><br/> v-pre 指令: 解析失效<br/> <div v-pre> {{text}} </div> <br/><br/><br/> v-once 指令: 只渲染一次 <br/> <div v-once > {{msg}} --- {{msg}} </div> <button @click="changeMsg">点我修改msg</button> </div> </body> <script> new Vue({ el:"#app", data:{ text:'<h1>我是 v-text 指令</h1>', html:'<h1>我是 v-html 指令</h1>', msg: '我是 v-once 指令' }, methods:{ changeMsg(){ this.msg = "haha"; } } }) </script> </html>
属性绑定,事件绑定,双向绑定
涉及指令
- v-bind 字面意思为绑定。是vue中提供的用户绑定属性的指令。v-bind可简写成 :
- v-on 事件绑定指令 可以简写成 @
- v-model 只能用于表单元素的双向绑定指令
属性绑定
- 在以前的开发中。我们使用title属性去设置鼠标悬浮的显示值,在vue 中可以使用V-bind去动态设置属性。
事件绑定
- 在以前的开发中。我们使用onclick等属性去设置点击事件,在vue 中可以使用v-on去设置方式,可简写成@
双向绑定
v-model 只能用于表单元素的双向绑定指令
练习
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns: xmlns: xmlns: xmlns: xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <!--属性绑定--> <img v-bind:src="url" width="400px" :alt="alt" :title="til"><br/> <a :href="url1" >百度一下</a><br/> <!--事件绑定--> <button v-on:click="clickMethod" >点我啊</button><br/> <input type="text" @blur="blurMethod" @focus="focusMethod" :value="val"/> <!--双向绑定--> <input type="text" v-model:username="username"/>---{{username}} </div> <script> new Vue({ el:"#app", data:{ url:"111.jpg", alt:'图片裂开', til:'跑车', url1:'https://baidu.com', val:'', username:123 }, methods:{ clickMethod() { alert("我来了") }, blurMethod(){ console.log("失去焦点") }, focusMethod(){ console.log("获取焦点") } } }) </script> </body> </html>
条件渲染 v-if v-else v-show
v-if
- v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。
v-else
- v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。
v-show
v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。
练习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <p v-if="num>=90">优秀</p> <p v-else-if="num>=80">良好</p> <p v-else-if="num>=70">及格</p> <span v-if="a"> 我是正确的 </span> <div v-show="ok" >我是show指令</div> <button @click="clickMethod">点我显示show指令</button> </div> <script> new Vue({ el:"#app", data:{ num:80, a:true, ok:false }, methods:{ clickMethod(){ this.ok=true } } }) </script> </body> </html>
列表渲染 v-for
v-for
用v-for指令根据遍历数组来进行渲染 前端不叫集合
有下面两种遍历形式
<div v-for="(item,index) in items"></div> //使用in,index是一个可选参数,表示当前项的索引
<div v-for="item in items"></div> //使用in
下面是一个例子,并且在v-for中,拥有对父作用域属性的完全访问权限
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <p align="center"> <input type="text" placeholder="姓名" v-model="username"> <button @click="seekMethod">搜索</button> </p> <p align="center"> <input type="text" placeholder="姓名" v-model="user.name"> <input type="text" placeholder="住址" v-model="user.address"> <input type="radio" name="sex" value="0" v-model="user.sex" checked/>女 <input type="radio" name="sex" value="1" v-model="user.sex"/>男 <button @click="adduser">添加</button> </p> <table border="1px" width="70%" align="center" cellpadding="15px"> <tr> <th>编号</th> <th>姓名</th> <th>住址</th> <th>性别</th> <th>操作</th> </tr> <tr v-for="(user,index) in users" align="center"> <td>{{index+1}}</td> <td>{{user.name}}</td> <td>{{user.address}}</td> <td>{{user.sex?"男":"女"}}</td> <td> <button @click="updateMethod(user)">修改</button> <button @click="deleteMethod(index)">删除</button> </td> </tr> </table> <p align="center"> <input type="hidden" readonly v-model="upuser.id"> <input type="text" placeholder="姓名" v-model="upuser.name"> <input type="text" placeholder="住址" v-model="upuser.address"> <input type="radio" name="sex" value="1" v-model="upuser.sex"/>男 <input type="radio" name="sex" value="0" v-model="upuser.sex"/>女 <button @click="updateuser">修改</button> </p> </div> <script> new Vue({ el:"#app", data:{ users:[ {id:1,name:'tony',address:'成都',sex:1}, {id:2,name:'java',address:'东莞',sex:0}, {id:3,name:'spring',address:'北京',sex:0}, {id:4,name:'springmvc',address:'重庆',sex:0}, {id:5,name:'mybatis',address:'佛山',sex:1}, ], user:{ id:undefined, name:undefined, address:undefined, sex:1 }, username:undefined, upuser:{ id:undefined, name:undefined, address:undefined, sex:undefined } }, methods:{ adduser(){ //计算id this.user.id = this.users.length+1; this.users.push(this.user); }, updateMethod(user){ this.upuser.id = user.id; this.upuser.name = user.name; this.upuser.address = user.address; this.upuser.sex = user.sex; }, updateuser(){ var newuser = this.users.map(user=>{ if (this.upuser.id == user.id){ user.name = this.upuser.name; user.address = this.upuser.address; user.sex = parseInt(this.upuser.sex); } return user; }) }, seekMethod(){ //判断名字是否存在 if (this.username){ var newArr = this.users.filter(user => { return user.name.indexOf(this.username) >= 0; }); this.users = newArr; } }, deleteMethod(index){ this.users.splice(index,1); } } }) </script> </body> </html>
效果图
过滤器
概述
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
过滤器分为两种
全局过滤器 所有Vue实例里面都可以使用Vue.filter
局部过滤器 当前的Vue实例里面可以使用
练习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <div>{{money}}</div> <div>{{money|moneyHandler}}</div> <div>{{birth}}</div> <div>{{birth|birthHandler}}</div> <div>{{sex==1?"男":"女"}}</div> <div>{{sex|sexHandler}}</div> </div> <hr> <div id="app2"> <div>{{money}}</div> <div>{{money|moneyHandler}}</div> <div>{{birth}}</div> <div>{{birth|birthHandler}}</div> <div>{{sex==1?"男":"女"}}</div> <div>{{sex|sexHandler}}</div> </div> </body> <script> //全局过滤器的声明 // Vue.filter("sexHandler",function (value) { // return value==1?"汉子":"妹子" // }) // Vue.filter("moneyHandler",function (value) { // return value.toFixed(2)//保留两位小数 // }) // Vue.filter("birthHandler",function (value) { // return value.getFullYear()+"-"+(value.getMonth()+1)+"-"+value.getDate()+" "+value.getHours()+":"+value.getMinutes()+":"+value.getSeconds() // }) let vue = new Vue({ //在过滤器里面无法访问data和methods filters:{ sexHandler(value){ return value==1?"汉子":"妹子" }, moneyHandler(value){ return value.toFixed(2)//保留两位小数 }, birthHandler:function (value) { return value.getFullYear()+"-"+(value.getMonth()+1)+"-"+value.getDate()+" "+value.getHours()+":"+value.getMinutes()+":"+value.getSeconds() } }, el: "#app", data: { money:9999.9193, birth:new Date(), sex:1 }, methods: { } }) let vue2 = new Vue({ el: "#app2", filters:{ sexHandler(value){ return value==1?"汉":"妹" }, moneyHandler(value){ return value.toFixed(3)//保留两位小数 }, birthHandler:function (value) { return value.getFullYear()+"-"+(value.getMonth()+1)+"-"+value.getDate() } }, data: { money:9999.9193, birth:new Date(), sex:1 }, methods: { } }) </script> </html>
监听器
作用
就是用来监听data里面的数据值是否发生变化。如果发生变化会触发监听器
练习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>10监听器的使用.html</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <div> <input type="text" v-model="age"> <input type="text" v-model="user.age"> </div> </div> </body> <script> let vue = new Vue({ el: "#app", //监听器 watch:{ age(newVal,oldVal){ console.log(newVal) console.log(oldVal) }, 'user.age':function (newVal,oldVal) { console.log(newVal) console.log(oldVal) } }, data: { age:18, user:{ age:100, } }, methods: { m1() { } } }) </script> </html>
综合练习,购物车
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <table border="1px" cellpadding="15px" width="70%" align="center"> <tr align="center"> <th> <input type="checkbox" v-model="checkedAll" @click="allMethod"> </th> <th>编号</th> <th>名称</th> <th>单价</th> <th>数量</th> <th>小计</th> <th>备注</th> <th>操作</th> </tr> <tr v-for="(good,index) in goodsList" align="center"> <td> <input type="checkbox" v-model="good.isChecked" @click="checkMethod(good)"> </td> <td>{{index + 1}}</td> <td>{{good.goodsName}}</td> <td>{{good.price}}</td> <td> <button @click="subMethod(good)">-</button> {{good.num}} <button @click="addMethod(good)">+</button> </td> <td>{{good.amount}}</td> <td>{{good.remark}}</td> <td> <button @click="delMethod(index)">删除</button> </td> </tr> <tr align="right"> <td colspan="8"> 总计:{{sumMoney}} <button @click="balance">结算</button> </td> </tr> </table> </div> <script> new Vue({ el:"#app", data:{ goodsList:[ {isChecked:false,id:1,goodsName:'小霸王1',price:200,num:1,amount:200,remark:'牛逼'}, {isChecked:false,id:2,goodsName:'小霸王2',price:300,num:1,amount:300,remark:'牛逼'}, {isChecked:false,id:3,goodsName:'小霸王3',price:200,num:1,amount:200,remark:'牛逼'}, {isChecked:false,id:4,goodsName:'小霸王4',price:100,num:1,amount:100,remark:'牛逼'}, {isChecked:false,id:5,goodsName:'小霸王5',price:50,num:1,amount:50,remark:'牛逼'}, {isChecked:false,id:6,goodsName:'小霸王6',price:10,num:1,amount:10,remark:'牛逼'}, ], sumMoney:0, checkedAll:false }, methods:{ allMethod(){ this.checkedAll = !this.checkedAll; this.goodsList.filter(good=>{ good.isChecked = this.checkedAll; }); /*计算总计*/ this.sumMoney = 0; this.goodsList.filter(good=>{ if (good.isChecked){ this.sumMoney += good.amount; } }) }, /*减数量*/ subMethod(good){ //商品数量不能少于1 if (good.num == 1){ return; } good.num--; /*计算小计*/ good.amount -= good.price; /*计算总计*/ this.sumMoney = 0; this.goodsList.filter(good=>{ if (good.isChecked){ this.sumMoney += good.amount; } }) }, /*加数量*/ addMethod(good){ good.num++; good.amount += good.price; /*计算总计*/ this.sumMoney = 0; this.goodsList.filter(good=>{ if (good.isChecked){ this.sumMoney += good.amount; } }) }, checkMethod(good){ /*点击按钮,按钮取反*/ good.isChecked = !good.isChecked; var flag = true; /*判断所有的是否都是选中状态*/ this.goodsList.filter(good=>{ if (!good.isChecked){ /*有一个没选中就将flag取false*/ flag = false; } }) /*判断完之后,再给顶部按钮赋值*/ this.checkedAll = flag; /*计算总计*/ this.sumMoney = 0; this.goodsList.filter(good=>{ if (good.isChecked){ this.sumMoney += good.amount; } }) }, balance(){ /*计算总计*/ this.sumMoney = 0; this.goodsList.filter(good=>{ if (good.isChecked){ this.sumMoney += good.amount; } }) alert("共支付"+this.sumMoney+"元") }, /*删除*/ delMethod(index){ this.goodsList.splice(index,1); } } }) </script> </body> </html>
效果图
生命周期
生命周期图
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>12生命周期.html</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{count}}</div>
<div id="myDiv">我是DIV的内容</div>
<input type="button" value="添加" @click="m1">
</div>
</body>
<script>
let vue = new Vue({
el: "#app",//el==element
//这个是可用的生命周期的第一个方法
//这个方法里面 data和methods还没有初始化,所以不能使用this.xxx来调用data里面的属性 及methods里面的方法
beforeCreate(){
console.log("beforeCreate---"+this.count)
},
//vue对象创建成功。此时可以 data和methods已初始化完成,可以使用this.xxx来调用data里面的属性和methods里面的方法
//【重点方法】一般在这里面发送网络请求。因为这个方法里面可以最早的访问到data和methods
created(){
console.log("created---"+this.count)
this.m1();
},
//这个方法是内存里面编译好的模板还没有挂载到浏览器之前执行的方法这里面不能操作页面的dom对象
beforeMount(){
console.log("beforeMount---"+this.count)
var myDiv = document.getElementById("myDiv");
myDiv.innerText="hello"
console.log(myDiv)
},
//【重点】页面挂载完成的方法,编译好的模板已把页面替换了 这里是最早可以操作页面dom对象的方法
mounted(){
console.log("mounted---"+this.count)
var myDiv = document.getElementById("myDiv");
myDiv.innerText="hello"
},
//data里面的数据有变化,而模板里面又取了data里面的值,那么就当这个值变化时就会被触发
beforeUpdate(){
console.log("beforeUpdate--"+this.count)
},
//beforeUpdate执行之后页面的模板里面的数据替换完成之后,回调的方法
updated(){
console.log("updated--"+this.count)
},
//页面vue对象被销毁时触发的方法 里面还可以访问 data和methods
beforeDestroy(){
console.log("beforeDestroy--"+this.count)
},
//页面vue对象已完成销毁 不能再访问data和methods
destroyed(){
console.log("destroyed--"+this.count)
},
data: {
count: 0,
userList:[]
},
methods: {
m1() {
console.log("m1")
var myDiv = document.getElementById("myDiv");
myDiv.innerText="m1m1m1m1m1m1m1m1m1"
this.count++;
}
}
})
</script>
</html>
组件使用
组件概念
组件的出现,是为了拆分Vue的代码块,不用同的组件划分不同的功能模块,以后我们需要某个功能时,就直接调用对应的组件即可
模块化:模块化是从代码的角度去分析的,方便代码分层开发,保证每个模块职责单一
组件:组件化是从界面的角度去划分的,如:分页组件、轮播、颜色选择、文件上传等
抽象 是吧公共的东西 像的东西抽出来 (好处:复用,公共的,缺点:代码的可读性直线下降)
图示
变量名说明:(组件的使用规范)
按java的开发思想,变量名往往是驼峰规则 myComponent my-component
在vue中定义组件可以使用驼峰规则,但是使用组件的时候如果存在驼峰,应该全部改成小写,并把每个单词用-连接 有点像springboot的yml配置文件的语法
声明组件
-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<my-component></my-component>
</div>
<!--定义组件模版-->
<template id="template1">
<div>
<p>{{p}}</p>
<button @click="clickMethod">点我</button>
<div>我是div标签</div>
</div>
</template>
<script>
/*自定义组件*/
var myComponent = {
template:"#template1",
data(){
return{
p:'我是p标签'
}
},
methods:{
clickMethod(){
this.p="ppp"
}
}
}
//绑定组件
Vue.component("my-component",myComponent);
new Vue({
el:"#app",
data:{},
methods:{}
})
</script>
</body>
</html>
组件中的data和methods
- 组件中也可以有自己的Data和methods,
- 组件里面的data必须是一个方法原因如下
- 组件在存在是为有复用,定义一个组件之后,可能会有多个地方使用到该组件。如果按data:{}的写法,多个组件会复用同一个data,降低组件的复用性,而定义为function则不会
私有组件的使用
上面的创建方法都是公有的组件,如果只想一个组件在某一个Vue实例里面使用,就可以使用私有组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <my-component></my-component> </div> <div id="app1"> <my-component></my-component> </div> <!--定义组件模版--> <template id="tem"> <div> <h1>{{h}}</h1> <button @click="clickMethod">点我</button> </div> </template> <script> <!--定义组件--> var myComponent = { template:"#tem", data(){ return{ h:"我是自定义模版" }; }, methods:{ clickMethod(){ this.h="我变了" } } } /*绑定组件,使用私有组件时,是在每个实例中单独绑定*/ //Vue.component("my-component",myComponent); new Vue({ el:"#app", components:{//私有组件 "my-component":myComponent }, data:{ }, methods:{ } }); new Vue({ el:"#app1", data:{ }, methods:{ } }); </script> </body> </html>
组件的切换
使用v-if v-else v-else-if去切换组件
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <!--定义两个按钮--> <button @click="flag=true">登陆</button> <button @click="flag=false">注册</button> <!--显示两个组件--> <div> <temp v-if="flag"></temp> <temp1 v-else></temp1> </div> </div> <!--定义两个组件模版--> <template id="temp"> <div> <h2>我是登陆组件</h2> <button>登陆</button> </div> </template> <template id="temp1"> <div> <h2>我是注册组件</h2> <button>注册</button> </div> </template> <script> /*定义公共组件1*/ Vue.component("temp",{ template: "#temp", data() { return{ }; }, hetmods:{} }); /*定义公共组件2*/ Vue.component("temp1",{ template: "#temp1", data() { return{ }; }, hetmods:{} }); new Vue({ el:"#app", data:{ flag:true }, hethods:{ } }) </script> </body> </html>
使用占位符切换组件
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <button @click="flagName = 'tem'">登陆</button> <button @click="flagName = 'tem1'">注册</button> <!--定义一个变量,用来切换模版--> <flag :is="flagName"></flag> <my-component></my-component> </div> <!--定义模版--> <template id="tem"> <div> <h1>登陆啊</h1> <button>登陆</button> </div> </template> <template id="tem1"> <div> <h1>注册啊</h1> <button>注册</button> </div> </template> <!--定义组件--> <script> Vue.component("tem",{ template:"#tem", data(){ return{ } }, methods:{ } }); Vue.component("tem1",{ template:"#tem1", data(){ return{ } }, methods:{ } }); new Vue({ el:"#app", data:{ flagName:undefined, }, methods:{} }); </script> </body> </html>
父子组件之间的传值
子组件直接获取父组件数据(父传子)
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> 父组件:{{msg}} <!--定义parent-msg变量,用于装入父组件的数据--> <my-component :parent-msg="msg"></my-component> </div> <!--定义子组件模版--> <template id="tem"> <div> 子组件:<span>{{title}}</span><br/> <!--定义一个按钮,定义事件传输数据--> <button @click="changeTitle">传递数据</button> </div> </template> <!--定义组件--> <script> Vue.component("my-component",{ template:"#tem", data(){ return{ title:"我是子组件" } }, /* parentMsg 对应 parent-Msg,这里进行定义变量类型与初始化*/ props:{ parentMsg:{ type:String, default:null } }, methods:{ changeTitle(){ this.title = this.parentMsg; } } }); new Vue({ el:"#app", data:{ msg:"我是父组件" }, methods:{ } }) </script> </body> </html>
子组件传递数据给父组件
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> 父组件:{{msg}} <my-component @click="clickMethod"></my-component> </div> <!--定义组件模版--> <template id="tem"> <div> 子组件:<span>{{title}}</span><br/> <button @click="clickTitle">数据传输</button> </div> </template> <script> /*定义组件*/ Vue.component("my-component",{ template:"#tem", data(){ return{ title:"我是子组件" } }, methods:{ clickTitle(){ this.$emit("click",this.title) } } }) new Vue({ el:"#app", data:{ msg:"我是父组件" }, methods:{ /*value就是 $emit("click",this.title) 中的第二个函数*/ clickMethod(value){ this.msg = value; } } }) </script> </body> </html>
父组件调用子组件的方法
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> </head> <body> <div id="app"> 父组件:{{msg}} <button @click="clickMethod">父组件按钮</button> <my-component ref="childRef"></my-component> </div> <!--定义组件模版--> <template id="tem"> <div> 子组件的属性:{{title}} </div> </template> <script> /*定义组件*/ Vue.component("my-component",{ template:"#tem", data(){ return{ title:"我是子组件中的属性" } }, methods:{ childMethod(value){ this.title = value; } } }) new Vue({ el:"#app", data:{ msg:"我是父组件" }, methods:{ clickMethod(){ this.$refs.childRef.childMethod("我是父组件调用子组件的方法") } } }) </script> </body> </html>
路由跳转
路由及作用
- 后端:对于普通网站同,所有的超链接都对应一个url地址,每个url都对应服务器上的资源
- 前端:对于单页面应用程序来说的,主要通过url中的#(hash)去实现的,(相当于a标签)
- 作用:就是用来做跳转的局部更新页面内容
vue路由跳转
代码演示
<!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> </head> <body> <div id="app"> <div> <router-link to="/login">登陆</router-link> <router-link to="/register">注册</router-link> <!--显示组件的标签--> <router-view></router-view> </div> </div> <!--定义模版--> <template id="login"> <div> <h1>登陆界面</h1> </div> </template> <template id="register"> <div> <h1>注册界面</h1> </div> </template> <script> /*定义组件*/ var login = { template:"#login", } var register = { template:"#register", } /*定义路由*/ var routerObj = new VueRouter({ routes:[ //{"path":"/",redirect:"/login"},//重定向 //{"path":"/", component:login}, {"path":"/login",component:login}, {"path":"/register",component:register} ] }) new Vue({ el:"#app", router:routerObj }) </script> </body> </html>
路由传参(地址传参及rest风格传参)
代码演示
<!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> </head> <body> <div id="app"> <router-link to="/login?username=tuoy&password=123">登陆</router-link> <router-link to="/register/xiaoyang/23">注册</router-link> <!--显示位置--> <router-view></router-view> </div> <!--定义模版--> <template id="login"> <div> <h1>我是登陆</h1> {{username}}---{{password}} </div> </template> <template id="register"> <div> <h1>我是注册</h1> {{name}}---{{age}} </div> </template> <script> /*定义组件*/ var login = { template:"#login", /*地址传参,数据在$route.query里面*/ created(){ this.username=this.$route.query.username; this.password=this.$route.query.password; }, data(){ return{ username:undefined, password:undefined } } } var register = { template:"#register", /*rest风格传参,数据在$route.params里面*/ created() { this.name = this.$route.params.name; this.age = this.$route.params.age; }, data(){ return{ name:undefined, age:undefined } } } /*创建路由*/ var routerObj = new VueRouter({ routes:[ {"path":"/login",component:login}, /*使用rest风格传参时,要在路由路径里面声明*/ {"path":"/register/:name/:age",component:register} ] }); new Vue({ el:"#app", router:routerObj, data:{}, methods:{} }) </script> </body> </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> </head> <body> <div id="app"> <router-link to="/login">登陆</router-link> <router-link to="/register">注册</router-link> <!--显示位置--> <router-view></router-view> </div> <!--定义模版--> <template id="login"> <div> <h1>登录界面</h1> <router-link to="/authLogin">验证码登陆</router-link> <router-link to="/pwdLogin">账号密码登陆</router-link> <router-link to="/scanLogin">扫码登陆</router-link> <router-view></router-view> </div> </template> <!--内嵌组件模版--> <template id="authLogin"> <div> <form action="#" method="post"> 手机号:<input type="text" name="username"><br/> 验证码:<input type="text" name="auth"><br/> <input type="button" value="登陆"> </form> </div> </template> <template id="pwdLogin"> <div> <form action="#" method="post"> 账号:<input type="text" name="username"><br/> 密码:<input type="password" name="pwd"><br/> <input type="button" value="登陆"> </form> </div> </template> <template id="scanLogin"> <div> <form action="#" method="post"> 扫码登陆<br/> <img src="22.jpg" width="100px" height="100px" align="center"> </form> </div> </template> <template id="register"> <div> <h1>注册界面</h1> </div> </template> <script> /*定义组件*/ var login = { template:"#login", data(){ return{} }, methods:{} } var register = { template:"#register", data(){ return{} }, methods:{} } /*定义内嵌组件*/ var authLogin = { template:"#authLogin" } var pwdLogin = { template:"#pwdLogin" } var scanLogin = { template:"#scanLogin" } /*创建路由*/ var routerObj = new VueRouter({ routes:[ //{"path":"/",redirect:"/login"}, {"path":"/login",component:login,children:[ {"path":"/authLogin",component:authLogin}, {"path":"/pwdLogin",component:pwdLogin}, {"path":"/scanLogin",component:scanLogin} ]}, {"path":"/register",component:register} ] }); new Vue({ el:"#app", router:routerObj, data:{}, methods:{} }) </script> </body> </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> </head> <body> <div id="app"> <div> <button @click="toLogin">登陆</button> <button @click="toRegister">注册</button> <br/> <router-view></router-view> </div> </div> <template id="login"> <div> <h1>登录界面</h1> </div> </template> <template id="register"> <div> <h1>注册界面</h1> </div> </template> <script> var login = { template:"#login" } var register = { template:"#register" } var routerObj = new VueRouter({ routes:[ {"path":"/",redirect:"/login"}, {"path":"/login",component:login}, {"path":"/register",component:register} ] }); new Vue({ el:"#app", router:routerObj, data:{}, methods:{ toLogin(){ this.$router.push("/login") }, toRegister(){ this.$router.push("/register") } } }) </script> </body> </html>
使用npm创建vue项目
创建创建项目
在dos窗口任意磁盘下输入命令
vue ui
在打开的网页上点击创建
输入项目名,包管理器选择为 npm ,git初始化关闭
选择手动预设,打开 Router , Vuex , Css Pre-processors 关闭 Linter / Formatter
配置中语法选择 3.x , Css Pre-processors 选择 Stylus
保存时尽量选则 : 创建项目,不保存预设
将创建好的项目拖到idea中打开,安装axios的依赖
//在项目的terminal窗口中,输入以下命令,安装依赖 npm install --save axios vue-axios //安装成功后,在项目中找到main.js文件,添加一下代码 import axios from 'axios' import VueAxios from 'vue-axios' //以下代码,添加进app中 .use(VueAxios, axios)
在项目中安装element-plus
//在项目的terminal窗口中,输入以下命令,安装element-plus npm install element-plus --save //安装成功后,在项目中找到main.js文件,添加一下代码 import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' //以下代码,添加进app中 .use(ElementPlus)
全部添加完成后,效果图如下
点击运行成功后的链接,若网页正常显示,怎项目配置成功