注意js中的“对象”的概念。很多地方都是用对象来解决的。还有js对象和json格式的关系。组件是一个js对象来表示的。但应该不是一个真正的js对象,因为数据都定义在函数里?看看ES6怎么说.
在控制格式时不要混合tab和空格使用,同一行只使用任意一种是可以的。推荐使用四个空格,因为不同编辑器对tab的支持不同
1. Vue 引言
渐进式
JavaScript 框架
- 渐进式
- 易用
- 高效
- 灵活 开发灵活 多样性
渐进式javascript框架: 让我们通过操作很少的DOM,甚至不需要操作页面中任何DOM元素,就很容易的完成数据和视图绑定 双向绑定 MVVM
注意: 日后在使用Vue过程中页面中不要在引入Jquery框架
2. Vue入门
2.1 下载Vuejs
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
2.2 Vue第一个入门应用
<div id="app">
{{ msg }} {{username}} {{pwd}}
<br>
<span>
{{ username }}
<h1>{{ msg }}</h1>
</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app", //element 用来给Vue实例定义一个作用范围
data:{ //用来给Vue实例定义一些相关数据
msg:"百知欢迎你,期待你的加入!",
username:"hello Vue!",
pwd :"12345",
},
});
</script>
总结:
1.vue实例(对象)中el属性: 代表Vue的作用范围 日后在Vue的作用范围内都可以使用Vue的语法
2.vue实例(对象)中data属性: 用来给Vue实例绑定一些相关数据, 绑定的数据可以通过{{变量名}}在Vue作用范围内取出
3.在使用{{}}进行获取data中数据时,可以在{{}}中书写表达式,运算符,调用相关方法,以及逻辑运算等
4.el属性中可以书写任意的CSS选择器[jquery选择器],但是在使用Vue开发是推荐使用 id选择器
注:
- Vue3中创建vueapp的方式已经改为:Vue.createApp(传入对象).mount(“#id”),类似工厂模式的思想
- data在Vue3写作函数,return 数据对象
- 由于js的特性,不在data(){return{}}中声明的变量也可以随时通过this.变量名新建。但是不能直接凭空出现变量名。
3. v-text和v-html
3.1 v-text
v-text
:用来获取data中数据将数据以文本的形式渲染到指定标签内部 类似于javascript 中 innerText
<div id="app" class="aa">
<span >{{ message }}</span>
<span v-text="message"></span>
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"百知欢迎您"
}
})
</script>
# 总结
1.{{}}(插值表达式)和v-text获取数据的区别在于
a.使用v-text取值会将标签中原有的数据覆盖 使用插值表达式的形式不会覆盖标签原有的数据
b.使用v-text可以避免在网络环境较差的情况下出现插值闪烁(js文件、数据还没有通过网络加载过来,html就开始渲染)
3.2 v-html
v-html
:用来获取data中数据将数据中含有的html标签先解析再渲染到指定标签的内部 类似于javascript中 innerHTML
<div id="app" class="aa">
<span>{{message}}</span>
<br>
<span v-text="message"></span>
<br>
<span v-html="message">xxxxxx</span>
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"<a href=''>百知欢迎您</a>"
}
})
</script>
4.vue中事件绑定(v-on)
4.1 绑定事件基本语法
<div id="app">
<h2>{{message}}</h2>
<h2 v-text="message"></h2>
<h2>年龄:{{ age }}</h2>
<br>
<input type="button" value="点我改变年龄" v-on:click="changeage">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
message:"hello 欢迎来到百知课堂!",
age:23,
},
methods:{ //methods 用来定义vue中时间
changeage:function(){
alert('点击触发');
}
}
})
</script>
# 总结:
事件 事件源:发生事件dom元素 事件: 发生特定的动作 click.... 监听器 发生特定动作之后的事件处理程序 通常是js中函数
1.在vue中绑定事件是通过v-on指令来完成的 v-on:事件名 如 v-on:click
2.在v-on:事件名的赋值语句中是当前时间触发调用的函数名
3.在vue中事件的函数统一定义在Vue实例的methods属性中
4.在vue定义的事件中this指的就是当前的Vue实例,日后可以在事件中通过使用this获取Vue实例中相关数据
4.2 Vue中事件的简化语法
<div id="app">
<h2>{{ age }}</h2>
<input type="button" value="通过v-on事件修改年龄每次+1" v-on:click="changeage">
<input type="button" value="通过@绑定时间修改年龄每次-1" @click="editage">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app", //element: 用来指定vue作用范围
data:{
age:23,
}, //data : 用来定义vue实例中相关数据
methods:{
changeage:function(){
this.age++;
},
editage:function(){
this.age--;
}
} //methods: 用来定义事件的处理函数
});
</script>
4.3 Vue事件函数两种写法
<div id="app">
<span>{{count}}</span>
<input type="button" value="改变count的值" @click="changecount">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
count:1,
},
methods:{
/*changecount:function(){
this.count++;
}*/
changecount(){
this.count++;
}
}
});
</script>
# 总结:
1.在Vue中事件定义存在两种写法 一种是 函数名:function(){} 推荐 一种是 函数名(){} 推荐
4.4 Vue事件参数传递
<div id="app">
<span>{{count}}</span>
<input type="button" value="改变count为指定的值" @click="changecount(23,'xiaohei')">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
count:1,
},
methods:{
//定义changecount
changecount(count,name){
this.count = count;
alert(name);
}
}
});
</script>
# 总结:
1.在使用事件时,可以直接在事件调用出给事件进行参数传递,在事件定义出通过定义对应变量接收传递的参数
5.v-show v-if v-bind
5.1 v-show
v-show
:用来控制页面中某个标签元素是否展示 底层使用控制是 display 属性
<div id="app">
<!--
v-show: 用来控制标签展示还是隐藏的
-->
<h2 v-show="false">百知教育欢迎你的加入!</h2>
<h2 v-show="show">百知教育欢迎你的加入这是vue中定义变量true!</h2>
<input type="button" value="展示隐藏标签" @click="showmsg">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
show:false,
},
methods:{
//定义时间
showmsg(){
this.show = !this.show;
}
}
})
</script>
# 总结
1.在使用v-show时可以直接书写boolean值控制元素展示,也可以通过变量控制标签展示和隐藏
2.在v-show中可以通过boolean表达式控制标签的展示课隐藏
5.2 v-if
v-if
: 用来控制页面元素是否展示 底层控制是DOM元素 操作DOM控制是否渲染
<div id="app">
<h2 v-if="false">百知教育</h2>
<h2 v-if="show">百知教育欢迎你的加入</h2>
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
show:false
},
methods:{
}
});
</script>
5.3 v-bind
v-bind
: 用来绑定标签的属性从而通过vue动态修改标签的属性
<div id="app">
<img width="300" v-bind:title="msg" v-bind:class="{aa:showCss}" src="baizhilogo.jpg" alt="">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
msg:"百知教育官方logo!!!!",
showCss:true,
},
methods:{
}
})
</script>
5.4 v-bind 简化写法
vue为了方便我们日后绑定标签的属性提供了对属性绑定的简化写法如 v-bind:属性名
简化之后 :属性名
<div id="app">
<img width="300" :title="msg" :class="{aa:showCss}" :src="src" alt="">
<input type="button" value="动态控制加入样式" @click="addCss">
<input type="button" value="改变图片" @click="changeSrc">
</div>
<!--引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el:"#app",
data:{
msg:"百知教育官方logo!!!!",
showCss:true,
src:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583490365568&di=52a82bd614cd4030f97ada9441bb2d0e&imgtype=0&src=http%3A%2F%2Fimg.kanzhun.com%2Fimages%2Flogo%2F20160714%2F820a68f65b4e4a3634085055779c000c.jpg"
},
methods:{
addCss(){
this.showCss= !this.showCss;
},
changeSrc(){
this.src = "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1925088662,1336364220&fm=26&gp=0.jpg";
}
}
})
</script>
6.v-for的使用
v-for
: 作用就是用来对对象进行遍历的(数组也是对象的一种)
<div id="app">
<span>{{ user.name }} {{ user.age }}</span>
<br>
<!--
通过v-for遍历对象中的各个属性
循环变量命名随意,但顺序是value,key,index(可以只传入部分参数)
-->
<table>
<thead>
<th>index</th>
<th>key</th>
<th>value</th>
</thead>
<tr v-for="(value,key,index) in user">
<td v-text="index"> </td>
<td>{{key}} </td>
<td v-html ="value"></td>
</tr>
</table>
<!--
通过v-for遍历数组
-->
<ul>
<li v-for="a,index in arr" >
{{index}} {{a}}
</li>
</ul>
<!--
通过v-for遍历数组中对象
:key 便于vue内部做重用和排序
循环变量命名随意
注意:必须提前存在user类!尽管可以后期添加属性!
-->
<ul>
<li v-for="user,index in users" :key="user.id">
{{index+1}} {{ user.name }} === {{ user.age }} ==== {{ user.content }}
</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
user:{age:23,name:"小陈"},
arr:["北京校区", "天津校区", "河南校区"],
users:[
{id:2,name:"xiaochen",age:23,content:"我曾经也是一个单纯的少年!"},
{id:1,name:"小白",age:20,content:"我曾经是一个邪恶的少年!"},
]
},
methods: {}
});
</script>
# 总结
1.:key 用来给vue内部提供重用和排序的唯一key ,用于识别每个节点
2.加不加括号无所谓
7 .v-model 双向绑定
v-model
: 作用用来绑定标签元素的值与vue实例对象中data数据保持一致,从而实现双向的数据绑定机制
v-bind只能单向绑定
<div id="app">
<input type="text" v-model="message">
<!-- 插值表达式也可以数据绑定 -->
<span>{{message}}</span>
<hr>
<input type="button" value="改变Data中值" @click="changeValue">
</div>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message:""
},
methods: {
changeValue(){
this.message='百知教育!';
}
}
});
</script>
# 总结
1.使用v-model指令可以实现数据的双向绑定
2.所谓双向绑定 表单中数据变化导致vue实例data数据变化 vue实例中data数据的变化导致表单中数据变化 称之为双向绑定
# MVVM架构 双向绑定机制
Model: 数据 Vue实例中绑定数据
VM: ViewModel 监听器 (联合数据和页面的抽象?)
View: 页面 页面展示的数据
8. 事件修饰符
修饰符
: 用来和事件连用,用来决定事件触发条件或者是阻止事件的触发机制
# 1.常用的事件修饰符
.stop
.prevent
.capture
.self
.once
.passive
8.1 stop事件修饰符
用来阻止事件冒泡
<div id="app">
<div class="aa" @click="divClick">
<!--用来阻止事件冒泡-->
<input type="button" value="按钮" @click.stop="btnClick">
</div>
</div>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {},
methods: {
btnClick(){
alert('button被点击了');
},
divClick(){
alert('div被点击了');
}
}
});
</script>
8.2 prevent 事件修饰符
用来阻止标签的默认行为
<!--用来阻止事件的默认行为-->
<a href="http://www.baizhibest.com/" @click.prevent="aClick">百知教育</a>
8.3 self 事件修饰符
用来针对于当前标签的事件触发 ===> 只触发自己标签的上特定动作的事件 只关心自己标签上触发的事件 不监听事件冒泡
<!--只触发标签自身的事件-->
<div class="aa" @click.self="divClick">
<!--用来阻止事件冒泡-->
<input type="button" value="按钮" @click.stop="btnClick">
<input type="button" value="按钮1" @click="btnClick1">
</div>
8.4 once 事件修饰符
once 一次 作用: 就是让指定事件只触发一次
<!--
.prevent : 用来阻止事件的默认行为
.once : 用来只执行一次特定的事件
-->
<a href="http://www.baizhibest.com/" @click.prevent.once="aClick">百知教育</a>
9. 按键修饰符
作用: 用来与键盘中按键事件绑定在一起,用来修饰特定的按键事件的修饰符
# 按键修饰符
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
9.1 enter 回车键
用来在触发回车按键之后触发的事件
<input type="text" v-model="msg" @keyup.enter="keyups">
9.2 tab 键
用来捕获到tab键执行到当前标签是才会触发
<input type="text" @keyup.tab="keytabs">
10. Axios 基本使用
10.1 引言
Axios
是一个http异步请求库,核心作用就是用来在页面中发送异步请求,并获取对应数据。
是一种ajax技术,底层都是基于web标准(?)中的xmlHttpRequest对象?
10.2 Axios 快速上手
中文网站:https://www.kancloud.cn/yunye/axios/234845
安装: https://unpkg.com/axios/dist/axios.min.js
10.2.1 GET方式的请求
//发送GET方式请求
axios.get("http://localhost:8989/user/findAll?name=xiaochen").then(function(response){
console.log(response.data);
}).catch(function(err){
console.log(err);
});
10.2.2 POST方式请求
//发送POST方式请求
axios.post("http://localhost:8989/user/save",{
username:"xiaochen",
age:23,
email:"xiaochen@zparkhr.com",
phone:13260426185
}).then(function(response){
console.log(response.data);
}).catch(function(err){
console.log(err);
});
10.2.3 axios并发请求
并发请求
: 将多个请求在同一时刻发送到后端服务接口,最后在集中处理每个请求的响应结果
//1.创建一个查询所有请求
function findAll(){
return axios.get("http://localhost:8989/user/findAll?name=xiaochen");
}
//2.创建一个保存的请求
function save(){
return axios.post("http://localhost:8989/user/save",{
username:"xiaochen",
age:23,
email:"xiaochen@zparkhr.com",
phone:13260426185
});
}
//3.并发执行
axios.all([findAll(),save()]).then(
axios.spread(function(res1,res2){ //用来将一组函数的响应结果汇总处理
console.log(res1.data);
console.log(res2.data);
})
);//用来发送一组并发请求
11. Vue 生命周期
生命周期钩子
====> 生命周期函数
在vue的生命周期中触发的函数
注:和组件的属性同级!不要写在methods里面!
热部署时似乎有些生命周期函数不再执行
Vue生命周期总结
1.初始化阶段
beforeCreate(){ //1.生命周期中第一个函数,该函数在执行时Vue实例仅仅完成了自身事件的绑定和生命周期函数的初始化工作,Vue实例中还没有 Data el methods相关属性
console.log("beforeCreate: "+this.msg);
},
created(){ //2.生命周期中第二个函数,该函数在执行时Vue实例已经初始化了data属性和methods等属性中相关方法
console.log("created: "+this.msg);
},
beforeMount(){//3.生命周期中第三个函数,该函数在执行时Vue将El中指定作用范围作为模板编译
console.log("beforeMount: "+document.getElementById("sp").innerText);
},
mounted(){//4.生命周期中第四个函数,该函数在执行过程中,已经将数据渲染到界面中并且已经更新页面
console.log("Mounted: "+document.getElementById("sp").innerText);
}
2.运行阶段
beforeUpdate(){//5.生命周期中第五个函数,该函数是data中数据发生变化时执行 这个事件执行时仅仅是Vue实例中data数据变化页面显示的依然是原始数据
console.log("beforeUpdate:"+this.msg);
console.log("beforeUpdate:"+document.getElementById("sp").innerText);
},
updated(){ //6.生命周期中第六个函数,该函数执行时data中数据发生变化,页面中数据也发生了变化 页面中数据已经和data中数据一致
console.log("updated:"+this.msg);
console.log("updated:"+document.getElementById("sp").innerText);
},
3.销毁阶段
2.0:(3.0中已被beforeUnmount()和unmounted()代替)
beforeDestory(){//7.生命周期第七个函数,该函数执行时,Vue中所有数据 methods componet 都没销毁
},
destoryed(){ //8.生命周期的第八个函数,该函数执行时,Vue实例彻底销毁
}
12. Vue中组件(Component)
12.1 组件作用
组件作用: 用来减少Vue实例对象中代码量,
日后在使用Vue开发过程中,可以根据 不能业务功能将页面中划分不同的多个组件,然后由多个组件去完成整个页面的布局,便于日后使用Vue进行开发时页面管理,方便开发人员维护。
- 单文件组件:一个组件一个模板
- 字符串模板:将组件写在字符串里
组件可以用一个js对象来定义
12.2 组件使用
12.2.1 全局组件注册
说明:全局组件注册给Vue实例,日后可以在任意Vue实例的范围内使用该组件
两个参数:组件名,对象
//1.开发全局组件,
//参数1: 组件的名称 参数2: 组件配置{} template:''用来书写组件的html代码
//template中必须有且只有一个root元素(必须在一个容器中),除非用v-if
Vue.component('login',{
template:'<div><h1>用户登录</h1></div>'
});
//2.使用全局组件 在Vue实例范围内
<login></login>
# 注意:
1.Vue.component用来开发全局组件
2.使用时需要在Vue的作用范围内根据组件名使用全局组件
3.如果在注册组件过程中使用驼峰命名组件的方式 在使用组件时 必须将驼峰的所有单词小写加入-线进行使用(<userLogin>使用时为<user-login>),应该是因为html对大小写不敏感。加个杠和小写名的组件做区分
12.2.2 局部组件注册
说明:通过将组件注册给对应Vue实例中一个components属性来完成组件注册,这种方式不会对Vue实例造成累加
- 第一种开发方式
//局部组件登录模板声明
let login ={ //具体局部组件名称
template:'<div><h2>用户登录</h2></div>'
};
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{ //用来注册局部组件
login:login //注册局部组件 组件名:变量名 当然也可以直接把变量写在这里
}
});
//局部组件使用 在Vue实例范围内
<login></login>
-
第二种开发方式
//1.声明局部组件模板 template 标签 注意:在Vue实例作用范围外声明 //当然用div也可以,不过创建时也会显示出来 //好处是有换行、有高亮! <template id="loginTemplate"> <h1>用户登录</h1> </template> //2.定义变量用来保存模板配置对象 let login ={ //具体局部组件名称 template:'#loginTemplate' //使用自定义template标签选择器即可 }; //3.注册组件 const app = new Vue({ el: "#app", data: {}, methods: {}, components:{ //用来注册局部组件 login:login //注册局部组件 } }); //4.局部组件使用 在Vue实例范围内 <login></login>
12.3 Prop的使用
作用:props用来给组件传递相应静态数据或者是动态数据的
12.3.1 通过在组件上声明静态数据传递给组件内部
//1.声明组件模板配置对象
let login = {
template:"<div><h1>欢迎:{{ userName }} 年龄:{{ age }}</h1></div>",
props:['userName','age'] //props作用 用来接收使用组件时通过组件标签传递的数据。相当于html标签的属性
}
//2.注册组件
const app = new Vue({
el: "#app",
data: {},
methods: {},
components:{
login //组件注册 变量名和组件名一样时可以省略
}
});
//3.通过组件完成数据传递
<login user-name="小陈" age="23"></login>
# 总结:
1.使用组件时可以在组件上定义多个属性以及对应数据
2.在组件内部可以使用props数组声明多个定义在组件上的属性名 日后可以在组件中通过{{ 属性名 }} 方式获取组件中属性值
12.3.2 通过在组件上声明动态数据传递给组件内部
//1.声明组件模板对象
const login = {
template:'<div><h2>欢迎: {{ name }} 年龄:{{ age }}</h2></div>',
props:['name','age']
}
//2.注册局部组件
const app = new Vue({
el: "#app",
data: {
username:"小陈陈",
age:23
},
methods: {},
components:{
login //注册组件
}
});
//3.使用组件
<login :name="username" :age="age"></login> //使用v-bind形式将数据绑定Vue实例中data属性,日后data属性发生变化,组件内部数据跟着变化
12.3.3 prop的单向数据流
单向数据流:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。—摘自官网
如果需要的prop过多,建议直接传入一个对象,可以随时在对象中添加新的属性。
12.4 组件中定义数据和事件使用
1. 组件中定义属于组件的数据
//组件声明的配置对象
const login = {
template:'<div><h1>{{ msg }} 百知教育</h1><ul><li v-for="item,index in lists">{{ index }}{{ item }}</li></ul></div>',
data(){ //使用data函数方式定义组件的数据 在templatehtml代码中通过插值表达式直接获取
return {
msg:"hello",
lists:['java','spring','springboot']
}//组件自己内部数据
}
}
2.组件中事件定义
const login={
template:'<div><input type="button" value="点我触发组件中事件" @click="change"></div>',
data(){
return {
name:'小陈'
};
},
methods:{
change(){
alert(this.name)
alert('触发事件');
}
}
}
# 总结
1.组件中定义事件和直接在Vue中定义事件基本一致 直接在组件内部对应的html代码上加入@事件名=函数名方式即可
2.在组件内部使用methods属性用来定义对应的事件函数即可,事件函数中this 指向的是当前组件的实例
12.5 向子组件中传递事件并在子组件中调用该事件
在子组件中调用传递过来的相关事件必须使用 this.$emit('函数名') 方式调用
//1.声明组件
const login = {//!!!这里插值表达式要用组建自己的数据!直接绑定父组件数据,不允许更改!!!
template:"<div><h1>百知教育 {{ uname }}</h1> <input type='button' value='点我' @click='change'></div>",
data(){
return {
uname:this.name
}
},
props:['name'],
methods:{
change(){
//调用vue实例中函数
this.$emit('find'); //调用组件传递过来的其他函数时需要使用 this.$emit('函数名调用')
}
}
}
//2.注册组件
const app = new Vue({
el: "#app",
data: {
username:"小陈"
},
methods: {
findAll(){ //一个事件函数 将这个函数传递给子组件
alert('Vue 实例中定义函数');
}
},
components:{
login,//组件的注册
}
});
//3.使用组件 把方法传递进去
<login @find="findAll"></login> //=====> 在组件内部使用 this.$emit('find')
简单来说,子组件决定触发哪个事件(如@click),然后通过$emit(‘’)将这个事件换个名字传递上去(总不能父组件也要跟着@click事件吧,肯定是一个自定义的事件)。然后父组件进行@此事件 的处理
由于单向数据流,子组件当然无法改变父组件中的数值;当需要子组件触发时(比如子组件是个按钮),可以用这种方法传递给上面
在组件中使用v-model
13.Vue中路由(VueRouter)
13.1 路由
路由:根据请求的路径按照一定的路由规则进行请求的转发从而帮助我们实现统一请求的管理
13.2 作用
用来在vue中实现组件之间的动态切换
13.3 使用路由
-
引入路由
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> //vue 路由js
-
创建组件对象
//声明组件模板 const login = { template:'<h1>登录</h1>' }; const register = { template:'<h1>注册</h1>' };
-
定义路由对象的规则
//创建路由对象 const router = new VueRouter({ routes:[ {path:'/login',component:login}, //path: 路由的路径 component:路径对应的组件 {path:'/register',component:register} ] });
-
将路由对象注册到vue实例
const app = new Vue({ el: "#app", data: { username:"小陈", }, methods: {}, router:router //设置路由对象 });
-
在页面中显示路由的组件
<!--显示路由的组件--> <router-view></router-view>
-
根据连接切换路由
<a href="#/login">点我登录</a> <!--必须有#!!--> <a href="#/register">点我注册</a>
13.4 router-link使用
作用:用来替换我们在切换路由时使用a标签切换路由
好处:就是可以自动给路由路径加入#不需要手动加入
<router-link to="/login" tag="button">我要登录</router-link>
<router-link to="/register" tag="button">点我注册</router-link>
# 总结:
1.router-link 用来替换使用a标签实现路由切换 好处是不需要书写#号直接书写路由路径
2.router-link to属性用来书写路由路径 tag属性:用来将router-link渲染成指定的标签
13.5 默认路由
作用:用来在第一次进入界面是显示一个默认的组件
const router = new VueRouter({
routes:[
//{ path:'/',component:login},
{ path:'/',redirect:'/login'}, //redirect: 用来当访问的是默认路由 "/" 时 跳转到指定的路由展示 推荐使用
{ path:'/login', component:login},
{ path:'/register', component:register},
]
});
13.6 路由中参数传递
- 第一种方式传递参数 传统方式
-
通过?号形式拼接参数
<router-link to="/login?id=21&name=zhangsan">我要登录</router-link>
-
组件中获取参数
const login = { template:'<h1>用户登录{{$route.query.name}}</h1>', data(){return {}}, methods:{}, created(){ //组件的生命周期 //可以在控制台输出this看到 console.log("=============>"+this.$route.query.id+"======>"+this.$route.query.name); } };
- 第二种方式传递参数 restful
-
通过使用路径方式传递参数
<router-link to="/register/24/张三">我要注册</router-link> var router = new VueRouter({ routes:[ {path:'/register/:id/:name',component:register} //定义路径中获取对应参数 ] });
-
组件中获取参数
const register = { template:'<h1>用户注册{{ $route.params.name }}</h1>', created(){ //console.log(this),发现是在params里面 console.log("注册组件中id: "+this.$route.params.id+this.$route.params.name); } };
13.7 嵌套路由
-
声明最外层和内层路由
<template id="product"> <div> <!--根容器别忘了!--> <h1>商品管理</h1> <router-link to="/product/add">商品添加</router-link> <router-link to="/product/edit">商品编辑</router-link> <router-view></router-view> <!--里面也要有router-view--> </div> </template> //声明组件模板 <script> const product={ template:'#product' }; const add = { template:'<h4>商品添加</h4>' }; const edit = { template:'<h4>商品编辑</h4>' }; </script>
-
创建路由对象含有嵌套路由
const router = new VueRouter({ routes:[ { path:'/product', component:product, children:[ {path:'add',component: add}, //如果写成同级别的路由,会替换 {path:'edit',component: edit}, //子路由不需要加/ ] }, ] });
-
注册路由对象
const app = new Vue({ el: "#app", data: {}, methods: {}, router,//定义路由对象 });
-
测试路由
<router-link to="/product">商品管理</router-link> <router-view></router-view> <!--第一个路由别忘了展示出来-->
14. Vue CLI 脚手架
14.1 什么是CLI
命令行界面(英语:command-line interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面(CUI)
14.2 什么是@Vue/CLI
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统。使用Vue 脚手架之后我们开发的页面将是一个完整系统(项目)。
老版本vue-cli,新版本@vue/cli
14.3 Vue CLI优势
- 通过
vue-cli
搭建交互式的项目脚手架。bootstrap css js jquery js 通过执行命令方式下载相关依赖 - 通过
@vue/cli
+@vue/cli-service-global
快速开始零配置原型开发 vue页面 vuejs vuerouter axios(一条命令) - 一个运行时依赖 (
@vue/cli-service
),该依赖:- 可升级; 一条命令
- 基于 webpack 构建,并带有合理的默认配置; webpack 项目打包方式 编译好的项目源码===>部署到服务器上直接使用
- 可以通过项目内的配置文件进行配置; 默认配置文件,通过修改默认配置文件搭建自己想要的环境
- 可以通过插件进行扩展。 vue v-charts elementui
- 一个丰富的官方插件集合,集成了前端生态中最好的工具。Nodejs Vue VueRouter webpack yarn
- 一套完全图形化的创建和管理 Vue.js 项目的用户界面
14.4 Vue CLI安装
1. 环境准备
1.1 下载nodejs
http://nodejs.cn/download/
windows系统: .msi 安装包(exe)指定安装位置 .zip(压缩包)直接解压缩指定目录
mac os 系统: .pkg 安装包格式自动配置环境变量 .tar.gz(压缩包)解压缩安装到指定名
1.2 配置nodejs环境变量
windows系统:
1.计算上右键属性----> 高级属性 ---->环境变量 添加如下配置:
NODE_HOME= nodejs安装目录
PATH = xxxx;%NODE_HOME%
2.macos 系统
推荐使用.pkg安装直接配置node环境
1.3 验证nodejs环境是否成功
node -v
1.4 npm介绍
node package mangager nodejs包管理工具 前端主流技术 npm 进行统一管理
maven 管理java后端依赖 远程仓库(中心仓库) 阿里云镜像
npm 管理前端系统依赖 远程仓库(中心仓库) 配置淘宝镜像
1.5 配置淘宝镜像
npm config set registry https://registry.npm.taobao.org
npm config get registry
1.6 配置npm下载依赖位置
windows:
npm config set cache "D:\nodereps\npm-cache"
npm config set prefix "D:\nodereps\npm_global"
mac os:
npm config set cache "/Users/chenyannan/dev/nodereps"
npm config set prefix "/Users/chenyannan/dev/nodereps"
1.7 验证nodejs环境配置
npm config ls
; userconfig /Users/chenyannan/.npmrc
cache = "/Users/chenyannan/dev/nodereps"
prefix = "/Users/chenyannan/dev/nodereps"
registry = "https://registry.npm.taobao.org/"
2.安装脚手架
#0.卸载脚手架
npm uninstall -g @vue/cli //卸载3.x版本脚手架
npm uninstall -g vue-cli //卸载2.x版本脚手架
#1.Vue Cli官方网站
https://cli.vuejs.org/zh/guide/
#2.安装vue Cli
npm install -g vue-cli
npm uninstall -g @vue/cli //3.x
3.第一个vue脚手架项目
# 1.创建vue脚手架第一个项目
#vue init webpack 项目名
vue create 项目名
#选择最后一个Manually select features
# 2.创建第一个项目(不同模板大差不差)
hello ------------->项目名
-build ------------->用来使用webpack打包使用build依赖
-config ------------->用来做整个项目配置目录
-node_modules ------>用来管理项目中使用依赖
-src ------>用来书写vue的源代码[重点]
+assets ------>用来存放静态资源 [重点]
components ------>用来书写Vue组件 [重点]
router ------>用来配置项目中路由[重点]
App.vue ------>项目中根组件[重点]
main.js ------>项目中主入口[重点]
-static ------>其它静态
-.babelrc ------> 将es6语法转为es5运行
-.editorconfig ------> 项目编辑配置
-.gitignore ------> git版本控制忽略文件
-.postcssrc.js ------> 源码相关js
-index.html ------> 项目主页
-package.json ------> 类似与pom.xml 依赖管理 不建议手动修改(webpack打包用,首页title在这里修改name属性)
-package-lock.json ----> 对package.json加锁
-README.md ----> 项目说明文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dy7CFNxw-1651996890688)(Vue实战.assets/1612204430582.png)]
main.js中写出,将App.vue组件作为入口默认访问,App.vue中的router-view默认为HelloWorld.vue(可修改index.js)
index.js返回Router对象,在里面配置routes
# 3.如何运行在项目的根目录中执行
npm start 运行前端系统
npm run dev 热部署启动(2.0)
npm run serve (3.0?) 根据配置文件,默认命令是serve和build
# 4.如何访问项目
serve模式:查看启动后提示的端口,默认从8080往后依次寻找。
build模式:项目被打包成静态文件,用http的方式访问部署在服务器上的资源。
# 5.Vue Cli中项目开发方式
注意: 一切皆组件 一个组件中 js代码 html代码 css样式
1. VueCli开发方式是在项目中开发一个一个组件对应一个==业务功能模块==,日后可以将多个组件组合到一起形成一个前端系统
2. 日后在使用vue Cli进行开发时不再书写html,编写的是一个个组件(组件后缀.vue结尾的文件),日后打包时vue cli会将组件编译成运行的html文件
> 一切皆组件,而组件又是用对象表示的
##### 4.如何开发Vue脚手架
`注意:在Vue cli 中一切皆组件`
```vue
<template>
<div id="app">
<!-- 这里显示HelloWorld.vue -->
<router-view/>
</div>
</template>
<script>
//将组件暴漏出去
export default {
name: 'App',
//还可以有
data(){
return {
msg:''
}
},
}
}
</script>
<style> <!--加上 scoped表示只在组件内有效。公共的写在app.vue里-->
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
```
子组件:在父组件中先import,再在components中注册
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WdLWflCp-1651996890690)(Vue实战.assets/1612205490346.png)]
15.在脚手架中使用axios
15.1 安装axios
npm install axios --save
配置main.js中引入axios
import axios from 'axios';
Vue.prototype.$http=axios;
使用axios
在需要发送异步请求的位置:
this.$http.get("url").then((res)=>{}) this.$http.post("url").then((res)=>{}) //这里this不用变
请求成功之后切换路由
if(res.data.success){
this.$router.push("");//切换路由(为什么是push?)
}
参数传递
//get
// 直接在 URL 上添加参数 ID=12345
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 也可以通过 params 设置参数:
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// post
axios.post('/user', {
firstName: 'Fred', // 参数 firstName
lastName: 'Flintstone' // 参数 lastName
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
15.2 监听路由变化
//这个例子是写在目标路由里
watch{ //和conpoments同级,用来监听
$routes:{
handler:function(val,oldVal){ //变化后的路由和变化前的(这是个路由对象)
console.log(val);
if(val.path=='/user'){
this.findAll();
}
},
deep:true //深度变化监听
}
}
15.3 路由间传参
如果是问号方式
this.$route.query.paramname
如果是restful风格
this.$route.params.id
例子是在created里面拿
15.4 路由钩子
beforeRouteUpdate //当前组件路由更新时
从子组件到父组件时可以添加事件
beforeRouteUpdate(to,from,next){
alert(); //此处可以再次查询
next()//放行;
}
16.Vue Cli脚手架项目打包和部署
# 1.在项目根目录中执行如下命令:
npm run build
#注意:vue脚手架打包的项目必须在服务器上运行不能直接双击运行,要放在http server上运行
# 2.打包之后当前项目中变化
在打包之后项目中出现dist目录,dist目录就是vue脚手架项目生产目录或者说是直接部署目录
# 3.可以将dist放在springboot的static文件夹下
改改资源路径 ,这个时候上下文路径变了
17.VueX 状态管理
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
曾经组件中数据是单向传递,现在值可以由vuex统一管理
17.1 简介 安装 使用state
全局状态管理,管理数据。
1.npm install vuex --save
2.在src下创建store文件夹,里面创建index.js
import Vue form 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state:{
conuter:0,
}
});
export default store;
Store对象的属性:
state: 全局管理共享数据
mutations: 对共享数据的修改方法
gatters: 对共享数据的计算属性,相当于computed
3.在main.js中
import store from './store'
new Vue({
el: '#app',
router,
template: '<App/>',
components: {App},
store,
})
4.使用
this.$store.state.counter
mutations
mutations:{
incrCounter(state){ //第一个参数默认state
state.count++
}
}
在其他组件:
this.$store.commit('incrCountr')
带参数:
mutations:{
incrCounter(state,n){ //第一个参数默认state
state.count = state.count + n
}
}
传参数时传对象:
mutation里的参数,最多传两个,第二个传个对象