简介
什么是Vue
- Vue是一个构建用户界面的前端框架
- 是一个轻量级的MVVM
- 数据驱动和组件化的前端开发
mvvm
-
MVVM(Model-View-ViewModel),其实就是所谓的数据的双向绑定mvc
-
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或者双向绑定框架来渲染页面。
开发准备
- 安装vue.js插件
- 新建web项目
- 添加vue.js
- 创建html
基础知识
初识Vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--插值表达式:由Vue对象解析数据,从model中取出数据,并渲染到指定页面位置-->
{{message}}
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
//创建vue js的核心对象,核心Vue对象就是vm
var vm = new Vue({
//配置vm对象管理的html
el: '#app',
//data配置就是数据模型M,它本身是一个字面量对象
//其中字面量对象属性名即数据名,字面量对象的属性值即数据值
data: {
message: 'hello vue',
num:20,
flage:true,
list:['aa','bb','dd'],
obj:{
name: 'xxx',
age:24
}
}
});
</script>
</body>
</html>
数据绑定
- vue中的数据显示到界面
- v-text v-html
<div id="app">
<!--
指令:html中的动态属性,所有的指令都是以v-开头的
v-text 将数据从model取出,并渲染到指定标签中。替换特殊符号
v-html 将数据从model取出,并渲染到指定标签中。原样展示
-->
<h1 v-text="message"</h1>
<p v-text="msg"></p>
<h1 v-html="message"></h1>
<p v-html="msg"></p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vue',
msg:'<a href="#">超链接</a>'
}
});
</script>
属性绑定
- v-bind:将vue变量绑定到属性上
- v-bind可以省略为‘ :’
<div id="app">
<!--
属性绑定指令
v-bind:HTML原生属性名称="data中的数据名称"
简化
v-bind: ===> :
-->
<h1 title="你好">{{message}}</h1>
<h1 v-bind:title="msg">{{message}}</h1>
<p :title="msg">{{message}}</p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vue',
msg:"你好啊"
}
})
</script>
事件绑定
- v-on:事件名=“函数名”
- 函数简化写法 v-on --> @
<div id="app">
<!--
事件绑定指令
v-on:事件名称="函数名称"
事件名称 click,focus,blur,change,dbclick,load...
简化
v-on: ===> @
-->
<p><button type="button" v-on:click="myFun1">按键1</button></p>
<p><button type="button" @click="myFun2">按键2</button></p>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vue'
},
//事件函数
method: {
myFun1: function () {
console.log("函数1执行了。。。")
},
//简化
myFun2() {
//在函数中可以使用data中的数据,但是必须以this(vue对象)调用
console.log("函数2执行了。。。" + this.message);
}
}
});
</script>
双向绑定
-
用法
- v-model:仅用于表单元素上
- 数据双向绑定指令:v-model=“data中的数据”
- 仅能用在表单元素上,文本框、单选按钮、复选框、下拉列表、多行文本框…
-
vue对象
<script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { message: 'hello vue', genderVal: 'female', login: false, hobbys: ['篮球v', '排球v'], edu: '', array: [] } }); </script>
-
文本框 (单行 多行)
<h1>文本框</h1> <p><input type="text" v-model="message"></p> <p><textarea cols="30" rows="10" v-model="message"></textarea></p> <h1>date中的数据:{{message}}</h1>
-
单选按钮
<h1>单选按钮</h1> <p> <label><input type="radio" name="gender" value="male" v-model="genderVal">男性</label> <label><input type="radio" name="gender" value="female" v-model="genderVal">女性</label> </p> <p>date中的数据:{{genderVal}}</p>
-
复选框
<h1>复选框</h1> <!-- 两种用法: 1.单用:绑定数据类型为boolean 2.多用:绑定数据类型为数组 --> <p> <label><input type="checkbox" v-model="login">十天免登录</label> </p> <p> <label><input type="checkbox" name="hobby" value="足球v" v-model="hobbys">足球</label> <label><input type="checkbox" name="hobby" value="篮球v" v-model="hobbys">篮球</label> <label><input type="checkbox" name="hobby" value="乒乓球v" v-model="hobbys">乒乓球</label> <label><input type="checkbox" name="hobby" value="羽毛球v" v-model="hobbys">羽毛球</label> <label><input type="checkbox" name="hobby" value="排球v" v-model="hobbys">排球</label> </p> <p>data中的数据:{{hobbys}}</p>
-
下拉列表
- 单选式
- 多选式
<h1>下拉列表</h1> <p> <select v-model="edu"> <option value="1">幼儿园</option> <option value="2">小学</option> <option value="3">中学</option> <option value="4">高中</option> <option value="5">大学</option> </select> </p> <p>data中的数据:{{edu}}</p> <p> <select multiple v-model="array"> <option value="aa">选项1</option> <option value="bb">选项2</option> <option value="cc">选项3</option> <option value="dd">选项4</option> <option value="ee">选项5</option> </select> </p> <p>data中的数据:{{array}}</p>
条件渲染
- v-if
- v-else
- v-else-if
- v-show
<div id="app">
<p><button type="button" @click="islLogin=!islLogin">登录与退出</button></p>
<div v-if="isLogin">当前登陆用户:{{username}}</div>
<div v-else>请登陆</div>
<p>data中的数据:{{isLogin}}</p>
<hr>
<div>
<div v-if="gender == '1'">男性</div>
<div v-else-if="gender == '2'">女性</div>
<div v-else-if="gender == '3'">保密</div>
<div v-else>有误</div>
</div>
<hr>
<!--
v-if 条件成立时渲染元素,条件不成立时不渲染元素
v-show 无论条件成立与否都渲染元素,通过css(display:none)来隐藏此标签
-->
<div v-show="isLogin">v-show指令</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vue',
username: '张三',
isLogin: true,
gender: '5'
}
})
</script>
-
列表渲染
- v-for of/in
- of / in
- index 索引
- :key 排序条件,一般用id
- 遍历对象
<div id="app"> <ul> <li v-for="name in nameList">{{name}}</li> </ul> <hr> <ul> <li v-for="name of nameList">{{name}}</li> </ul> <hr> <ul> <li v-for="(name, index) of nameList">{{name}}--{{index}}</li> </ul> <hr> <ul> <li v-for="(name, index) of nameList" :key="index">{{name}}--{{index}}</li> </ul> <hr> <table border="1" width="500" align="center"> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>成绩</th> </tr> <tr v-for="student in studentList" :key="student.id"> <td>{{student.id}}</td> <td v-text="student.name"></td> <td v-text="student.age"></td> <td v-text="student.score"></td> </tr> </table> </div> <script type="text/javascript" src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { message: 'hello vuejs', nameList: ['张三', '李四', '王五', '赵柳', '小七', '大巴'], studentList: [ {id: 101, name: '小明', age: 20, score: 90}, {id: 102, name: '小红', age: 21, score: 87}, {id: 103, name: '小张', age: 23, score: 76}, {id: 104, name: '小王', age: 20, score: 69}, {id: 105, name: '小李', age: 22, score: 100} ] } }); </script>
计算属性
- 作用:处理data中的数据
- 计算属性的函数使用与data中的属性一致
<div id="app">
<p>{{message}}</p>
<!--复杂运行尽量不在插值表达式中进行-->
<p>{{message.split(' ').reverse().join(' ')}}</p>
<!--计算属性的使用方式:计算属性的函数使用与data中的属性一致-->
<p>{{msg}}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
//计算属性: 处理data中的数据
computed: {
msg: function (){
var array = this.message.split(' ');
array.reverse();
//计算属性的函数必须有返回值
return array.join('$$');
}
}
});
</script>
监听器
- 作用:监听data数据的变化
- 函数名称与数据名保持一致
<div id="app">
<p>姓名:<input type="text" v-model="name"></p>
<p>{{name}}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs',
name: ''
},
//侦听器:监听data数据的变化
watch: {
/**
* 侦听函数
* 名称:与侦听的数据名一致
* 参数:1数据变化之后的值 2数据变化之前的值
*/
name: function (newVal, oldVal){
console.log('新数据', newVal);
console.log('老数据', oldVal);
}
}
});
</script>
生命周期
-
钩子函数:生命周期的某个阶段会执行的函数
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TqWeHOY9-1661774468138)(E:\JAVA\DLJD\我的笔记\myImages\Vue知识点总结\lifecycle.16e4c08e.png)]
-
<div id="app"> <p>{{ message }}</p> <p><button type="button" @click="message += '2022'">按钮</button></p> </div> <script type="text/javascript" src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { message: 'hello vuejs' }, methods: { myFun(){ console.log('myFun....') } }, //生命周期钩子函数 beforeCreate(){ //vue对象已经创建,但是data数据与method函数没有初始化 console.log('beforeCreate', this.message); // this.myFun(); }, created(){ //data数据与method函数已经初始化完成 console.log('created', this.message); this.myFun(); }, beforeMount(){ //mount挂载:解析模板(动态的内容被替换成静态数据) //模板没有被解析 var dom = document.querySelector('#app > p'); console.log('beforeMount', dom.innerHTML); }, mounted(){ //模板已经解析完成 var dom = document.querySelector('#app > p'); console.log('mounted', dom.innerHTML); }, beforeUpdate(){ //vue对象运行期间,当data数据变化时 //data数据已经变化,但没有渲染到页面 console.log('beforeUpdate-data', this.message); var dom = document.querySelector('#app > p'); console.log('beforeUpdate-html', dom.innerHTML); }, updated(){ //data数据已经变化,也渲染到页面 console.log('updated-data', this.message); var dom = document.querySelector('#app > p'); console.log('updated-html', dom.innerHTML); }, beforeDestroy(){ }, destroyed(){ } }); </script>
样式绑定
- Class与
- 样式类
- 动态样式类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
.red {
color: red;
}
.size {
font-size: 25px;
}
.back {
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<h2>内联样式</h2>
<div style="color: red; font-size: 20px; background-color: green;">{{message}}</div>
<h2>样式类</h2>
<div class="red size back">{{message}}</div>
<h2>对象</h2>
<div :class="{red: true, size: true, back: false}">{{message}}</div>
<div :class="obj">{{message}}</div>
<h2>数组</h2>
<div :class="['red', 'size', flag?'back':'']">{{message}}</div>
<p><button type="button" @click="flag = !flag">按钮</button></p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs',
obj: {
red: true,
size: true,
back: true
},
flag: true
}
});
</script>
</body>
</html>
过滤器
-
作用:处理数据
-
全局定义
Vue.filter(过滤器名,过滤函数(源数据,参数1,参数2...){})
-
局部定义
var vm = new Vue({ ... filters: { 过滤函数名: (source){ return source+'局部过滤器' } } });
<div id="app">
<p>{{ message }}</p>
<p>{{ message | msgFormat1 }}</p>
<p>{{ message | msgFormat2('夏向向') }}</p>
<p>{{ message | msgFormat3('小王','小盼') }}</p>
<p>{{ message | msgFormat4 }}</p>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
/**
* 过滤器:处理数据,数据格式化
* 1.全局定义
* Vue.filter(过滤器名,过滤函数(源数据,参数1,参数2...){})
*/
Vue.filter('msgFormat1', function (source) {
//过滤器返回值,处理数据后的结果
//只改一个
// return source.replace('vue', 'java');
//改所有匹配的(区分大小写)
// return source.replace(/vue/g, 'java');
//改所有匹配的(不区分大小写)
return source.replace(/vue/ig, 'java');
});
//传入一个或多个参数
Vue.filter('msgFormat2',function (source,param) {
return source.replace(/vue/ig, param);
});
Vue.filter('msgFormat3',function (source,param1,param2) {
return source.replace(/vue/ig, param1+" and "+param2);
});
var vm = new Vue({
el: '#app',
data: {
message: '我爱vue,vue爱我,Vue真牛!'
},
//2.局部过滤器
filters: {
//过滤函数
msgFormat4(source){
return source+'局部过滤器'
}
}
});
</script>
组件
初识组件
- 可复用
全局组件
-
Vue.component(组件名称, 组件配置);
-
三种使用方式
<div id="app">
<!--组件使用:以html标签的形式,组件名为html标签名-->
<login></login>
<login></login>
<register></register>
<tabs></tabs>
</div>
<!--方式三:使用组件模板-->
<template id="tabs">
<div>
<table border="1" width="300">
<tr>
<th>表头1</th>
<th>表头2</th>
<th>表头3</th>
</tr>
<tr>
<td>数据11</td>
<td>数据12</td>
<td>数据13</td>
</tr>
<tr>
<td>数据21</td>
<td>数据22</td>
<td>数据23</td>
</tr>
</table>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
/**
* 全局组件
* Vue.component(组件名称, 组件配置);
*/
//方式一
Vue.component('login', {
//html模板
template: '<div><h1>用户登录组件</h1></div>'
});
//方式二 (不推荐,麻烦)
var register = Vue.extend({
template: '<div><h1>用户注册组件</h1></div>'
});
Vue.component('register', register);
//方式三:使用组件模板
Vue.component('tabs', {
template: '#tabs'
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
}
});
</script>
局部组件
- 写好函数,再把函数注册到组件中
<div id="app">
<pageheader></pageheader>
<pagefooter></pagefooter>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
var pageheader = {
template: '<div><h1>页面顶部组件</h1></div>'
};
var pagefooter = {
template: '<div><h1>页面底部组件</h1></div>'
};
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
//注册局部组件
components: {
//字面量对象
//属性名为组件的名称,属性值为组件的配置
pageheader: pageheader,
//字面量对象的简化写法(属性名与属性值一致时可简化)
pagefooter
}
});
</script>
组件命名注意事项
- 1.不能与Html标签名冲突
- 2.名称为多个单词组成
- 中划线间隔:my-main,list-nav,user-add
- 驼峰:myMain, listNav, userAdd, StudentList
- 注意:组件在使用时,必须使用中划线
- 3.组件的html部分,仅能有一个根标签,仅会渲染第一个标签中的内容
<div id="app">
<my-main></my-main>
<!-- 无效写法: <MyMain1></MyMain1> -->
<my-main1></my-main1>
<mymain2></mymain2>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
Vue.component('my-main',{
template: '<div><h1>使用-命名:my-main</h1></div>'
}),
Vue.component('MyMain1',{
template: '<div><h1>使用驼峰命名:MyMain1</h1></div>'
}),
Vue.component('mymain2',{
template: '<div>第一个div</div><div>第二个div</div>'
})
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
}
});
</script>
组件中的data
- data数据可以被模板组件调用
- 模板组件还可以调用事件函数
<div id="app">
<list-nav></list-nav>
<list-nav></list-nav>
<list-nav></list-nav>
</div>
<template id="listNav">
<div>
<p><button type="button" @click="changeAge">按钮</button></p>
<ul>
<li><a href="#">首页--{{msg}}</a></li>
<li><a href="#">新闻--{{username}}</a></li>
<li><a href="#">用户--{{age}}</a></li>
<li><a href="#">关于--{{address}}</a></li>
</ul>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
/**
* 组件的数据与函数
* data: 数据
* 组件中的数据data是一个函数,并且函数有返回值,返回值为字面量对象(此字面量对象为数据)
* 好处:
* 1.数据可以拥有自己的过程代码(对数据进行初步处理)
* 2.组件中的数据在组件复用时,每个组件实例中的数据是隔离(相互不影响)
*/
var listNav={
template: '#listNav',
data() {
//数据函数体:初步数据处理
return {
msg: '组件',
username: 'zhangsan',
age: 24,
address: '北京'
}
},
//组件中的事件函数
methods: {
changeAge(){
this.age++;
}
}
}
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
components: {
listNav
}
});
</script>
组件传值
父传子
-
父组件可以将属性和方法传给子组件
-
在父组件中绑定子组件属性,和传递方法
<sub-component v-bind:msg="message" v-on:demo="test"></sub-component>
<div id="app">
<h2>父组件中的数据:{{message}}</h2>
<p><button type="button" @click="message+='666'">修改父组件中的数据</button></p>
<!--传
在父组件中使用子组件时通过子组件标签的属性进行传递
v-bind:子组件内部接收数据的变量名称="父组件中的数据"
传递函数:
v-on:在子组件内调用函数名称="父组件中的函数名"
-->
<!-- <sub-component v-bind:msg="message" v-on:demo="test"></sub-component>-->
<sub-component :msg="message" @demo="test"></sub-component>
</div>
<template id="sub">
<div>
<h2>子组件中的数据:{{username}}</h2>
<h2>子组件接收父组件传递的数据: {{msg}}</h2>
<p><button type="button" @click="myFun">调用父组件中的函数</button></p>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
//子组件
var subComponent={
template: '#sub',
data() {
return{
username:'tom'
}
},
/**
* 接收
* 通过props配置来接收父组件传递过来的数据
*
* props的值
* 1.数组: 数组中存放就是接收数据的变量名称
* 2.对象:属性名称即变量名称,其值为数据类型
*/
// props: ['msg']
props: {
msg: String
},
methods: {
myFun(){
/**
* 在子组件中通过触发调用,来调用父组件中传递过来的函数
* $emit('调用的函数名', 函数参数)
*/
// this.demo()
this.$emit('demo', 'hello');
}
}
};
//父组件
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
methods: {
test(param){
console.log('test函数执行了...'+param)
}
},
components: {
subComponent
}
});
</script>
子传父
-
子组件将属性和方法传递给父组件
-
1.向子组件传数据,添加一个关键字(修饰符)
<sub-component :msg.sync="message" @damo="test"></sub-component>
-
2.通过触发调用函数,向父组件传递数据
//$emit('update:props中的变量名称', 传递的数据值); this.$emit('update:msg','你好vuejs');
<div id="app">
<h2>父组件中的数据:{{message}}</h2>
<p><button type="button" @click="message += '666'">修改父组件中的数据</button></p>
上面是父组件<hr color="red">下面是子组件
<!--1.向子组件传数据,添加一个关键字(修饰符)-->
<sub-component :msg.sync="message" @damo="test"></sub-component>
</div>
<template id="sub">
<div>
<h2>子组件中的数据: {{username}}</h2>
<h2>子组件接收父组件传递的数据: {{msg}}</h2>
<p><button type="button" @click="myFun">调用父组件中的函数</button></p>
<p><button type="button" @click="msg += '123'">修改子组件中的props</button></p>
<p><button type="button" @click="changeMsg">子传父的方法</button></p>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript">
//子组件
var subComponent={
template: '#sub',
data() {
return {
username: 'xxx'
}
},
/**
* 父组件中的数据变化,子组件中的数据也会变化
* 但是,如果子组件中的props数据变化,父组件中的数据是不会变化。数据传递为单向, 父 --> 子
* 注意: porps的数据是不允许修改的,仅允许读取
*/
props: {
msg: String
},
methods:{
myFun() {
this.$emit('demo', 'hello')
},
changeMsg(){
/**
* 2.通过触发调用函数,向父组件传递数据
* $emit('update:props中的变量名称', 传递的数据值);
*/
this.$emit('update:msg','你好vuejs');
}
}
};
//父组件
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
methods: {
test(param){
console.log('test函数执行了....' + param)
}
},
components:{
subComponent
}
});
</script>
单文件组件
<template>
<!--组件中的html部分-->
<div></div>
</template>
<script>
//组件的js代码区域
export default {
data(){
return {}
},
methods: {},
props: {},
watch: {},
computed: {},
components: {},
mounted(){}
}
</script>
<style scoped>
/**
css代码区域
注意:样式是整个项目中所有的.vue文件共享
scoped属性表示当前组件中的样式为私有样式
*/
.demo{
font-size: 30px;
}
</style>
路由
初识路由
- 作用:用于切换组件、组件之间数据传递
- 创建项目后,导入
vue-router.js
文件
<div id="app">
<h1>欢迎使用路由</h1>
<!--
4.路由的使用
<router-link>标签,路由导航标签,它会被解析为一个超链接
<router-view>标签,路由出口,通过点击导航标签,组件渲染的位置
-->
<router-link to="/login">登录</router-link>
<router-link to="/reg">注册</router-link>
<!--组件渲染,既展示路由指定的组件-->
<router-view></router-view>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
//1.定义组件
var login = {template: '<div><h1>登录组件</h1></div>'};
var register = {template: '<div><h1>注册组件</h1></div>'};
//2.定义路由
//路由作用:切换组件,组件之间的数据传递
var router = new VueRouter({
//路由模式,默认hash,历史模式history
// mode: 'history',
//路由列表: 路径与组件的对应
routes: [
/**
* 单个路由对象
* path: 路由路径字符串,值必须以斜杠开头
*/
{path: '/login', component: login},
{path: '/reg', component: register}
]
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
//3.在vue对象中设置路由
router
});
</script>
路由传参
- 路径拼接传参
- 路径传参
<div id="app">
<h1>欢迎使用路由</h1>
<!--路径拼接传参-->
<router-link to="/login?username=tom&password=123">登录</router-link>
<!--路径传参-->
<router-link to="/reg/101/zhangsan">注册</router-link>
<router-view></router-view>
</div>
<template id="login">
<div>
<h1>登录组件</h1>
<!--
在路由中两种对象
$router对象 表示全局路由对象,就是VueRouter对象本身
$route对象 表示当前路由,通过路径导航到组件对应的路由对象
$route对象,在当前路由对象中有一个属性query,记录所有路径拼接传参的数据
-->
<p>{{$route.query}}</p>
<p>{{$route.query.username}}</p>
<p>{{$route.query.password}}</p>
</div>
</template>
<template id="reg">
<div>
<!--
$route对象,在当前路由对象中有一个属性params,记录所有路径传参的数据
-->
<h1>注册组件</h1>
<p>{{$route.params}}</p>
<p>{{$route.params.id}}</p>
<p>{{$route.params.username}}</p>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
//1.定义组件
var login = {template: '#login'};
var register = {template: '#reg'};
//2.定义路由
var router = new VueRouter({
routes: [
{path: '/login', component: login},
{path: '/reg/:id/:username', component: register}
]
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
//3.在vue对象中设置路由
router
});
</script>
编程式导航
- 在路由导航的同时,导航到指定的历史记录
- 两种传参方式
<div id="app">
<h1>欢迎使用路由</h1>
<h2>声明式导航</h2>
<p>
<router-link to="/login">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-link to="/user">用户</router-link>
<router-link to="/emp">员工</router-link>
</p>
<h2>编程式导航</h2>
<p>
<button type="button" @click="doRedirect('login')">登录按钮</button>
<button type="button" @click="doRedirect('reg')">注册按钮</button>
<button type="button" @click="doRedirect('user')">用户按钮</button>
<button type="button" @click="doRedirect('emp')">员工按钮</button>
</p>
<p>
<button type="button" @click="doBackward">后退</button>
<button type="button" @click="doForward">前进</button>
</p>
<router-view></router-view>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
//1.定义组件
var login = {template: '<div><h1>登录组件{{$route.query}}</h1></div>'};
var register = {template: '<div><h1>注册组件{{$route.query}}</h1></div>'};
var user = {template: '<div><h1>用户组件{{$route.params}}</h1></div>'};
var emp = {template: '<div><h1>员工组件{{$route.params}}</h1></div>'};
//2.定义路由
//路由作用:切换组件,组件之间的数据传递
var router = new VueRouter({
routes: [
//name: 路径的名称
{path: '/login', name: 'login', component: login},
{path: '/reg', name: 'reg', component: register},
{path: '/user', name: 'user', component: user},
{path: '/emp', name: 'emp', component: emp}
]
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
//3.在vue对象中设置路由
router,
methods: {
/**
* 编程式导航
* $router 全局路由对象
*
* push() 在路由导航的同时,在历史列表中添加一个新的历史记录
* replace() 在路由导航的同时,在历史列表中替换最后一个历史
* go() 导航到指定的历史记录
*/
doRedirect(name){
// this.$router.replace('/'+name);
/*两种传参方式*/
//1.query
// this.$router.push({
// path: '/' + name,
// query: {
// id: 10,
// name: '张三'
// }
// });
//2.params
//编程式导航通过params传递参数时,不能使用路径进行导航,应该使用路径名称
this.$router.push({
// path: '/'+name,
name: name,
params: {
id: 20,
name: '李四'
}
});
},
doForward(){
this.$router.go(1);
},
doBackward(){
this.$router.go(-1);
}
}
});
</script>
嵌套路由
- 定义路由时,使用children属性,可以定义子路由
- 子路由的路径写在父路径的后面
<div id="app">
<h1>欢迎使用路由</h1>
<p>
<router-link to="/login">登录</router-link>
<router-link to="/main">主页</router-link>
</p>
<!--路由出口:提供给一级路由-->
<router-view></router-view>
</div>
<template id="main">
<div>
<h2>导航</h2>
<p>
<router-link to="/main/user">用户</router-link>
<router-link to="/main/emp">员工</router-link>
<router-link to="/main/dept">部门</router-link>
</p>
<!--路由出口:提供给嵌套路由-->
<router-view></router-view>
</div>
</template>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/vue-router.js"></script>
<script type="text/javascript">
//1.定义组件
var login = {template: '<div><h1>登录组件</h1></div>'};
var main = {template: '#main'};
var user = {template: '<div><h1>用户组件</h1></div>'};
var emp = {template: '<div><h1>员工组件</h1></div>'};
var dept = {template: '<div><h1>部门组件</h1></div>'};
//2.定义路由
var router = new VueRouter({
routes: [
{path: '/login', name: 'login', component: login},
{
path: '/main',
name: 'main',
component: main,
//嵌套路由,子路由列表
children: [
//嵌套路由:1.相对路径:不以斜杠开头(父路径+子路由路径) 2绝对路径:以斜杠开头
// 如果子路由路径为user,真实路径为/main/user
// 如果子路由路径为/user,真实路径为/user
{path: 'user', name: 'user', component: user},
{path: 'emp', name: 'emp', component: emp},
{path: 'dept', name: 'dept', component: dept}
]
}
]
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello vuejs'
},
router
});
</script>
Node.js
简介
-
Node.js 是一个开源和跨平台的 JavaScript 运行时环境
-
作用:以前需要把 js 代码写到html文件中执行,现在可以直接执行了
#例如执行 hello.js node hello.js
npm
-
Nodejs package managerment
-
npm是node提供的一个包管理系统,类似于maven
-
通过npm去安装依赖包,就不需要在页面上使用script标签引入了
-
建立 node.js 项目
npm init
-
建立完项目会生成package.json文件
- 这个文件是项目的描述文件
- 里面不能写注释
-
脚本:json文件中的 scripts
... "scripts": { "test": "echo 'hello nodeJs'" }, ...
#运行脚本 npm run test
-
管理当前项目依赖:dependencies
-
如使用命令
npm install md5
-
生成node_modiles文件夹,此文件夹存放第三方的依赖
-
-
命令
#配置淘宝下载源 #设置 npm config set registry https://registry.npm.taobao.org #查看 npm config get registry #根据package.json文件中依赖下载当前项目中所有的依赖 npm install #简化写法 npm i #安装指定包 npm install 包名 #下载指定版本 npm install 包名@版本号 #搜包的网站:https://www.npmjs.com/ #安装指定包到dev环境 npm install --save-dev 包名 #也可简写为 npm i -D 包名 npm i -D axios@0.26.1 #安装到全局(非当前项目目录,在所有的项目中都可使用) npm install -g 包名 #npm镜像加速配置 npm install -g cnpm --registry=https://registry.npm.taobao.org #查看版本 nnpm -v #卸载 npm uninstall 包名 npm uninstall -g 包名 #设置全局安装目录,注意:需要修改环境变量 #查看 npm config get prefix #设置 npm config set prefix 位置 npm config set prefix D:\RuanJian\nodejs_cache\npm #设置npm缓存目录 #查看 npm config get cache #设置 npm config set cache 位置
dependencies:开发与发布环境都可使用的依赖
devDependencies:开发环境使用的依赖
搭建vuejs项目
vue-cli
-
vue-cli(vue脚手架),它是一个专门为单页面应用快速搭建繁杂的脚手架
-
它可以轻松的创建新的应用程序而且可用于自动生成vue和webpack的项目模板。
-
vue-cli是有Vue提供的一个官方cli,专门为单页面应用快速搭建繁杂的脚手架。
-
它是用于自动生成vue.js+webpack的项目模板
-
安装vue-cli脚手架
npm install -g @vue/cli@4.5.19
-
执行命令配置项目
vue create 项目名称 #使用图形化界面创建项目 vue ui
-
打开npm工具窗口:package.json右键—>show npm Spripts
包与模块
-
包:前端项目
-
模块:一个独立的js文件(类似于Java中类)
模块的导出
-
demo / user.js
//模块:定义的变量和函数都是私有的 var id=20; var username='xxx'; var password='13413'; var login=function (){ console.log('登录函数'); } //导出:普通导出,可以导出多个变量和函数,也可以多次导出 export {id,username,password,login}
-
student / index.js
var stu = { id: 10, name: '张三', age: 21, address: '上海' } //导出默认:仅能导出一次,一次仅能有一个对象 export default stu;
模块的导入
-
main.js
//启动项目即被执行 import Vue from 'vue' import App from './App.vue' import router from './router' //导入user.js导出的文件 import {id,username,password,login} from "@/demo/user"; // import {id,username,password,login} from "./demo/user"; //导入student import student from './student' //打印导入的值 console.log("用户ID", id); console.log("用户名", username); console.log("密码", password); login(); console.log("学生", student); Vue.config.productionTip = false new Vue({ router, render: h => h(App) }).$mount('#app')//这里定义了入口组件
组件与路由
组件
-
复用组件:可复用
-
页面式组件:不复用的,独此一份
-
Dept.vue
<template> <div> <h1>部门页面</h1> <table border="1" width="450" align="center"> <tr> <th>部门编号</th> <th>部门名称</th> <th>部门位置</th> </tr> <tr v-for="dept in deptList" :key="dept.id"> <td>{{dept.id}}</td> <td>{{dept.name}}</td> <td>{{dept.loc}}</td> </tr> </table> </div> </template> <script> export default { name: "Dept", data() { return { deptList: [] } }, methods: { listHandle(){ this.deptList = [ {id: 11, name: '研发部', loc: '北京'}, {id: 12, name: '生产部', loc: '上海'}, {id: 13, name: '采购部', loc: '深圳'}, {id: 14, name: '销售部', loc: '杭州'}, {id: 15, name: '人力部', loc: '苏州'} ]; } }, mounted() { this.listHandle(); } } </script> <style scoped> </style>
路由
-
用于加载组件
-
两种加载方式:立即加载 延迟加载
-
index.js
import Vue from 'vue' import VueRouter from 'vue-router' //立即导入(立即加载)组件 import Home from '../views/Home.vue' //使用路由 Vue.use(VueRouter) //路由列表 const routes = [ {path: '/', name: 'Home', component: Home}, //组件延迟加载 {path: '/about', name: 'About', component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')}, {path: '/dept', name: 'dept', component: () => import(/* webpackChunkName: "dept" */ '@/views/Dept.vue')}, {path: '/emp', name: 'emp', component: () => import(/* webpackChunkName: "emp" */ '@/views/Emp.vue')} ] const router = new VueRouter({ routes }) export default router
入口组件中添加路由
-
在App.vue入口组件中添加路由
-
App.vue
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/dept">部门</router-link> | <router-link to="/emp">员工</router-link> </div> <router-view/> </div> </template> ...
Axios
简介
- 专业的异步请求工具
- Axios 中文文档 :https://www.axios-http.cn/
- 官网简介
- Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。
- 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。
- 在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
安装和导入axios
-
安装
$ npm install axios
-
在XXX.Vue文件
Axios的使用
四种请求
axios.get(url, config)
axios.post(url, data, config)
axios.put(url, data, config)
axios.delete(url, config)
传递参数
/* 传递参数:
* get与delete在配置中定义一个属性params(路径拼接传递参数)
*post与put提价数据时在data参数填写数据即可,data参数本身是一个字面量对象,提交时会被转换为json字符串提交
* axios发送请求时,ContentType内容类型默认为application/json
*/
axios({
method: 'post',
url: '/test',
data: {
id: 10,
name: 'zhangsan'
}
});
axios.get('/getTest',{
params: {
id: 20,
name: 'list'
}
});
axios.post('/postTest', {
id: 30,
name: 'wangwu'
});
接收响应:连调函数
/**
* 注意:如果需要进行跨域异步请求,路径必须写成完整
* 连调函数then()成功回调,catch()失败回调
* 此两个函数的参数也是一个函数,回调处理程序
* 回调函数的参数为axios封装的一个对象,在此对象中有一个属性data为服务端真正响应的数据
*/
var that = this;
axios.get('http://localhost:8080/dept/list').then(function(res){
console.log('响应内容', res.data.data);
//在function函数中this关键字指向发生了改变
that.deptList = res.data.data;
console.log('deptList:',that.deptList)
}).catch(function (){
});
箭头函数
/**
* 箭头函数:类似于Java lamda表达式
* 替代匿名函数
* function(){}
* () => {}
*
* function(id){}
* id => {}
*
* function(id,name){}
* (id,name) => {}
*
* function(){console.log();}
* () => console.log();
* 好处:函数体内不改变this关键字的指向
*/
axios.get('http://localhost:8080/dept/list').then(res => {
if(res.data.code == 0){
this.deptList = res.data.data;
}
}).catch(res => console.log(res));
封装为工具
-
上面的写法还是太麻烦
-
创建xxx.js文件,配置axios
//导入axios import axios from 'axios'; //创建axios对象,进行公共配置 var instance = axios.create({ //基础路径 baseURL: 'http://localhost:8080', //请求超时时间 timeout: 10000 }); //发送请求允许携带凭证(cookie) instance.defaults.withCredentials=true; //请求拦截器:在axios发送请求之前作出处理 instance.interceptors.request.use(config => { console.log('请求的配置对象', config); //设置请求头部信息 config.headers['myToken'] = 'hello axios'; return config; }, error => Promise.reject(error)); //响应拦截器:在axios收到响应之后作出处理 instance.interceptors.response.use(response => { //将服务器响应的数据从axios的封装中取出,直接返回 return response.data; }, error => Promise.reject(error)); //导出axios对象 export default instance;
-
使用工具类
-
在main.js中导入,并挂载到全局
//导入axios工具类 import request from '@/utils/request' ... //将axios工具类对象挂载到全局(Vue对象),$ajax是自定义的属性名,用的时候保持一致就可以 Vue.prototype.$ajax = request;
-
在xxx.vue中使用
//this 是vue对象 this.$ajax.get('/dept/list').then(res => { console.log('服务端响应的数据:', res) if(res.code == 0){ this.deptList = res.data; } }).catch(res => console.log(res));
-
(){
});
#### 箭头函数
```js
/**
* 箭头函数:类似于Java lamda表达式
* 替代匿名函数
* function(){}
* () => {}
*
* function(id){}
* id => {}
*
* function(id,name){}
* (id,name) => {}
*
* function(){console.log();}
* () => console.log();
* 好处:函数体内不改变this关键字的指向
*/
axios.get('http://localhost:8080/dept/list').then(res => {
if(res.data.code == 0){
this.deptList = res.data.data;
}
}).catch(res => console.log(res));
封装为工具
-
上面的写法还是太麻烦
-
创建xxx.js文件,配置axios
//导入axios import axios from 'axios'; //创建axios对象,进行公共配置 var instance = axios.create({ //基础路径 baseURL: 'http://localhost:8080', //请求超时时间 timeout: 10000 }); //发送请求允许携带凭证(cookie) instance.defaults.withCredentials=true; //请求拦截器:在axios发送请求之前作出处理 instance.interceptors.request.use(config => { console.log('请求的配置对象', config); //设置请求头部信息 config.headers['myToken'] = 'hello axios'; return config; }, error => Promise.reject(error)); //响应拦截器:在axios收到响应之后作出处理 instance.interceptors.response.use(response => { //将服务器响应的数据从axios的封装中取出,直接返回 return response.data; }, error => Promise.reject(error)); //导出axios对象 export default instance;
-
使用工具类
-
在main.js中导入,并挂载到全局
//导入axios工具类 import request from '@/utils/request' ... //将axios工具类对象挂载到全局(Vue对象),$ajax是自定义的属性名,用的时候保持一致就可以 Vue.prototype.$ajax = request;
-
在xxx.vue中使用
//this 是vue对象 this.$ajax.get('/dept/list').then(res => { console.log('服务端响应的数据:', res) if(res.code == 0){ this.deptList = res.data; } }).catch(res => console.log(res));
-