记录小坑:在vue中使用axios时,在.then的function函数中使用的this关键字并不是vue的this关键字!
解决办法:先把this关键字定义在外面: var this = this; 然后就可以在function中使用了。
1. 总结
1.一个页面中只能存在一个Vue实例,不能创建多个Vue实例.
2.vue实例中el属性代表vue实例的作用范围,日后再vue实例作用范围内可以使用{{data属性中的变量名}}直接获取data中变量名对应属性值.
3.vue实例中data属性用来给当前vue实例绑定自定义数据,日后绑定数据可以在vue实例作用范围内直接使用{{变量名}}方式获取.
4.使用{{}}进行data中数据获取时,可以在{{}}取值语法中进行算术运算 逻辑运算以及调用相关类型的相关方法.
5.vue实例中el属性可以书写任何css选择器,但是推荐使用id选择器,因为一个vue实例只能作用于一个具体作用范围.
1. 基本命令
v-text、v-html
v-on:click="test()"、简化写法@click()
v-if、v-show、v-bind
v-for、v-model
2.computed计算属性
# 作用:用来在vue实例中完成相关业务计算工作,日后在将某个数据渲染页面时如果该数据需要经过业务处理之后再渲染就可以使用computed。
# 好处:提升vue运行性能,主要使用computed进行计算相关处理,会将第一次计算结果进行缓存,便于日后页面多次使用。
# 理解:就是一个方法在多个地方调用多次,这个方法就只会执行一次,而methods的方法在多个地方调用多次,会执行多次。
3.事件修饰符
# 事件修饰符
.stop 作用:用来阻止事件冒泡
.prevent 作用:用来阻止标签的默认行为
.self 作用:只监听自身标间触发的事件
.once 作用:该事件只触发一次
# 语法
@事件名.事件修饰符="事件处理函数" ====> @click.stop="test()"
4.按键修饰符
# 按键修饰符
.enter
.tab
.delete(捕获“删除”和"退格"键)
.esc
.space
.up
.down
.left
.right
> 例如:用来在触发回车按键之后的事件
<input type="text" v-model="msg" @keyup.enter="test()"/>
5. axios
官方定义:axios异步请求库 并不是vue官方库 第三方异步库 在vue中推荐axios
特性:1.从浏览器中创建XMLHttpRequests。
2.从node.js创建http请求。
3.支持Promise API
4.拦截请求和相应。
5.转换请求数据和响应数据。
6.取消请求。
7.自动转换JSON数据
8.客户端支持防御XSRF
1.基本使用
# 1.axios发送异步请求
axios.get("http://localhost:8080/demo?id=21&name=zhangsan")
.then(function(res){console.log(res)}) //代表请求之后处理
.catch(function(err){console.log(err)}) //代表请求失败后处理
# 2.axios发送各种异步请求
a. axios.get("url?id=21")
.then(function(res){res.data})
.catch(function(err){console.log(err)})
b. axios.post("url",{id:1,name:"zhangsan"})
.then(function(res){res.data})
.catch(function(err){console.log(err)})
# 注意: post这种传参方式是json的方式,后端需要用@RequestBody来接收
# 3.axios创建默认实例发送请求
//创建axios的配置对象
var instance = axios.create({
baseURL:"http://localhost:8080/",
timeout:5000,
})
//发送get请求
instance.get("url?id=21")
.then(function(res){res.data})
.catch(function(err){console.log(err)})
# 注意:这里有了实例之后就可以直接拿实例来 点 请求方式,以后只需要改这个实例的Url即可。
2.拦截器
# interceptors
作用:用来将axios中共有参数,响应公共处理交给拦截器处理,减少axios发送请求时代码冗余
# axios拦截器类型
a. 请求拦截器,这个config参数是请求的配置对象,打印一下就知道是什么了。
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
b. 响应拦截器,这个response参数代表从后端返回来的数据,可以进行对齐修改,或者做一些判断
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
6.ES6语法
1. 变量声明
不推荐使用var的原因:使用var声明的变量存在作用范围混淆的问题
es6 ==> let const 推荐使用这两个关键字声明变量
let :用来声明局部变量
好处:作用范围严谨,从代码声明开始到代码块结束,一般在声明基本变量使用推荐使用let;
const:用来声明js中常量
好处:一旦被赋值不能被修改,声明js中对象或数组时推荐使用const
例如:const student = {id:1,name:"zhangsan"};
对象中的属性可变,对象地址不可变。
2. 箭头函数
在使用匿名函数时,推荐使用es6中箭头函数 =>
必须得是匿名的,如果是 function test(){},这种则不可以使用箭头函数;
注意:
- 当箭头函数没有参数或参数大于1个时,必须加入()。
- 当箭头函数只有一个参数时,()可以省略不写。
- 当函数体中只有一行代码时,大括号可以省略不写。
- 箭头函数和原来的匿名函数最大的区别,箭头函数没有自己的this,匿名函数存在自己的this
以前:
function (){
};
现在:
(参数)=>{
函数体
}
3.模板字符串
使用语法:` ` (键盘数字1的左边)
使用这个特性语法就不用担心转义字符串的问题了。
let html = `<div><button οnclick="test(id)">点我</button></div>`
4. 对象定义
在定义对象时如果对象属性名和变量名一致,写一个即可。
例如:
let id = 21;
let name = "张三";
let age = 23;
const emp = {id,name,age};
以前的写法:
const emp = {id:id,name:name,age:age};
7.组件 component
什么是SPA 单页面应用?
就是日后项目中只有一个页面 ====> index.html
Vue推荐开发方式要求:一个应用中只能存在一个vue实例。
为了严格遵循SPA开发方式在VUE中提供了 vue组件 Component
组件:1.组件减少vue根实例代码量
2.一个组负责完成项目中一个功能或者一组功能实现业务隔离
3.组件还可以在vue实现复用
1. 全局组件
注意:无论使用全局组件还是局部组件,都必须在组件template中加入唯一根元素
直接注册vue根实例组件
参数1: 组件名称,参数2:组件的配置对象
Vue.component('login',{
template: `<div><h2>用户登录</h2> <form acrion=""></form></div>`
}) //注册这个就是全局组件
Vue.component('register',{
template: `<div><h2>用户注册</h2> <form acrion=""></form></div>`
}) //注册这个就是全局组件
在使用时直接
<login></login> or <register></register>
2.局部组件
注意:无论使用全局组件还是局部组件,都必须在组件template中加入唯一根元素
只能在注册组件中使用组件
new Vue({
el:"",
data:{},
methods:{},
created:{},
components:{
add:{
template:`<div><h2>用户添加</h2><form action=""></form></div>`
}
}//局部组件注册 这个components 是加s的。
})
在使用时直接
<add></add>
3.总结
局部组件中可以使用全局组件
组件中定义 data methods computed 生命周期函数 以及 子组件
//1. 组件中定义相关数据
//a. 全局组件
Vue.component('组件名',{
template:`<div><h1>{{id}}</h1></div>`,//用来定义组件html代码
//这里的data是一个方法,需要return对象回去
data(){ //用来定义组件自己的数据 日后在组件html中直接使用{{}}进行取值
return{
//例如:
id:1,
}
},
methods:{},
computed:{},
components:{},//定义组件自己的组件
created(){},
})
//b.局部组件
const app = new Vue({
......
components:{//用来定义局部组件
login:{
template:`<div><h1>{{id}}</h1></div>`;
//这里的data是一个方法,需要return对象回去
data(){
return{
id: 1,
}
},
methods:{},
computed:{},
components:{},//定义组件自己的组件
created(){}
}
}
})
4.父向子组件传递数据
单向数据流:父组件改变则会刷新影响子组件的数据
//props 传递静态数据:就是写死一个数据
//动态数据:数据可变
//父组件向子组件传递数据:
// a.传递静态数据 在组件使用标签上 声明静态数据 key=value 在组件内部定义使用 props数组进行接收数据才可以
// b.组件标签上声明 :key="value" 组件内部使用定义使用 props数组进行接收数据才可以
//例子
components:{
add:{
props:['title','count'],
template:`<div>
<button @click="zizeng()">用户添加</button>
<h1>{{title}}---{{copyTitle}}---{{count}} -- {{copyCount}}</h1>
</div>`,
data(){
return{
copyTitle : this.title+"评价",
copyCount : this.count
}
},
methods:{
zizeng(){
console.log(this.copyCount++);
}
}
}
}
5. 父向子传递事件,并返回数据给父组件
传递事件时的方法名不能使用驼峰命名法,所以全部小写
<!-- 使用组件
在使用组件时向组件传递事件 直接在对应组件标签上定义传递事件即可
@key=value
@传递事件名 = "父组件中传递事件名"
-->
//在组件中使用 的方法中使用以下方法调用传递过来的事件名:
// this.$emit('传递事件名',返回给父组件的参数);
例子:
<body>
<div id="app" align="center">
{{count}}
<login title = "1" @testperent="testPerent"></login>
</div>
</body>
<script>
const login = {
props:['title'],
template : `
<div>
<h1>{{title}}</h1>
<button @click="testChild">点我触发子组件</button>
</div>
`,
data(){
return{
count:19,
}
},
methods:{
testChild(){
console.log(this.count)
alert("我是子组件");
this.$emit('testperent',this.count);//在这调用父组件传过来的值,参数1:传递事件名
//参数2:返给会父组件方法的数据,可以定义多个 逗号分隔
}
}
}
const vue = new Vue({
el:"#app",
data:{
count:2
},
methods:{
testPerent(count){ //这个参数的count是子组件传过来的值
alert('我是父组件');
this.count = count;
console.log("我接受到了子组件传过来的值",count);
}
},
components:{
login,
}
})
</script>
6.slot插槽
插槽:slot
作用:用来扩展现有组件 让组件变得更加灵活 类似计算机的usb接口
具名插槽:带有名字的插槽
在子组件的template中使用<slot name ="aa"></slot> 标签代表给这个组件附上了一个插槽接口(usb)
在使用这个组件时 给组件标签中的标签加上slot属性,属性值为aa,那么这个标签将去找slot插槽为aa的插槽赋值,那么组件中的slot标签将会成为这个传过来的标签。
例子:
<body>
<div id="app" align="center">
{{count}}
<login>
<span slot="aa">啊啊啊啊啊</span> //这里的slot属性代表去找子组件的slot插槽name为aa的去赋值
<h1 slot="bb">我要给bb赋值</h1>//这里的slot属性代表去找子组件的slot插槽name为bb的去赋值
<button slot="cc" @click="testPerent()">点我改变父级count</button> //这个同上
//点击上面这个button去调用父级的方法
</login>
</div>
</body>
<script src="js/Mouse.js"></script>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<script>
const login = {
template:`
<div>
//这个插槽标签代表一个usb占位,在使用的时候哪里需要这个就去给这个插槽赋值即可
<slot name ="aa"></slot>
<button>我是一个按钮</button>
<slot name = "bb"></slot>
<slot name = "cc"></slot>
</div>
`,
}
const vue = new Vue({
el:"#app",
data:{
count:2
},
methods:{
testPerent(count){
this.count++;
}
},
components:{
login,
}
})
</script>
8.Vue-Router
1.基本使用
步骤:
- 下载vue router.js并在页面中进行引入
- 创建路由规则并在vue实例中注册
const router = new VueRouter({
route:[
{path:"/login",component:组件名,name:"路由名字"},
//重定向
{path:'/',redirect:"/login",name:'Login'},
//防止误输入
{path:'/*',component:notFount,name:"NotFount"},
})
-
展示路由组件
-
添加切换路由链接(就是a标签,例:“跳转到登录页面</a”>),
<body>
<div id="app" align="center">
<!--3.显示路由组件标签 -->
<router-view></router-view>
</div>
</body>
<script src="js/Mouse.js"></script>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<!-- 这个必须放在vue.js的下面,因为是vue中的插件 -->
<script src="js/vue-router.js"></script>
<script>
const login = {
template:`<div><button>用户登录</button></div>`,
}
const register = {
template:`<div><button>用户注册</button></div>`
}
const notFount = {
template:`<div><h1>404 页面走丢了!!!</h1></div>`
}
//1.创建路由配置规则
const router = new VueRouter({
// //这里面的每一个对象就是一个路径,这里的routes没有r
routes:[
//配置根路径去访问login,这里使用 redirect代表重定向到login,重定向必须指定路径,不能指定组件
{path:'/',redirect:"/login",name:'Login'}, //这里的name代表给这个对象起名字
{path:'/login', component:login,name:'Login'},
{path:"/register",component:register,name:"Register"},
{path:'/*',component:notFount,name:"NotFount"}, //这个放在最后面,防止用户输入错误
]
});
const vue = new Vue({
el:"#app",
router:router, //2.注册路由
})
2.切换路由的两种方式
# 1.标签方式切换
1. <a href = "#/路由路径">
2. <router-link to="/路由路径">
3. <router-link :to="{path:'/路由路径'}">
4. <router-link :to="{name:'路由名称'}">
# 2.js方式切换(比如在完成方法逻辑后需要跳转到某个组件)
1. this.$router.push('/路由路径');
2. this.$router.push({path:'/路由路径'})
3. this.$router.push({name:'路由名称'})
# 3.
this.$route 代表当前路由对象
this.$router 代表路由管理器对象
3. 解决同一个路由多次切换报错
const originalPush = VueRouter.protoType.push;
VueRouter.prototype.push = function push(location){
return originalPush.call(this,location).catch(err => err);
}
4.切换路由传参方式
标签形式切换路由
地址栏传递参数分为两种方式
# 1.queryString(就是?的方式) 在js的组件方法中使用 this.$route.query.key
举例:
<router-link to="{path:'/login',query:{name:'zs',password:'123'}}"></router-link>
<router-link to="{name:'Login',query:{name:'zs',password:'123'}}"></router-link>
# 2.restful路径传递参数 在js的组件方法中使用this.$route.params.key
举例:
<router-link to="{path:'/login',params:{name:'zs',age:'12'}"></router-link>
<router-link to="{name:'Login',params:{name:'zs',age:'12'}"></router-link>
> 注意:如果使用restful,那么路由的path的路径必须这么写 以上面的login路径为例
> /login/:name/:age
> 定义几个参就必须传几个参,路径的参数名必须和传过来的参数名一致
# 在js的组件方法中这样接收参数
const login = {
template:`
<div><h1>用户登录</h1></div
`,
created(){
//全部都是使用当前路由对象,不是路由管理器对象
//如果是query的方式
this.$route.query.name;
//如果是restful的方式
this.$route.params.name;
}
}
5.路由嵌套
子路由的组件必须在父路由的组件中加上 ,这样才会显示标签
const router = new VueRouter({
routes:[
//子路由不能有/,因为 '/' 代表根。
{path:"/users",component:oneComponent,name:"users",children:[
{path:"add",component:addComponent,name:"addUser"},
{path:"modify",component:modifyComponent,name:"modifyUser"},
]
},
{path:"/",redirect:"/users"},
]
})
9. 使用Vue-cli , node.js
1.安装node.js
2.安装vue-cli
b:测试命令能否执行 vue init
vue的声明周期
-
什么是vue生命周期
定义:指的就是vue实例在页面中创建到销毁的整个过程
-
vue生命周期钩子 ===> vue生命周期函数
生命周期函数 钩子特点:伴随着vue实例生命周期过程中自动触发的,不需要人为手动触发
-
三个阶段:初始化阶段、运行阶段、销毁阶段。
const vm=new Vue({
el:"#app",
data:{
msg:['金飞鹏',"新华电脑"]
},
methods:{
add:function () {
console.log("add被执行");
this.count++
},
sub:function () {
console.log("sub被执行");
this.count--
}
},
//初始化阶段
beforeCreate:function(){
//第一个生命周期函数,这个函数执行时,仅仅完成自身内部事件和生命周期函数注入
//在这个方法中获取不到vue实例中的东西
console.log("beforeCreate:",this.msg);
},
created:function(){
//第二个生命周期函数 这个函数执行时,完成自身内部事件和生命周期函数注入,包括自定义data,methods,computed等属性注入和校验工作
//在这个方法中可以获取到vue实例中的东西
console.log("created:",this.msg);
},
beforeMount(){
//第三个生命周期函数,这个函数执行时,el执行html还是一个原始模板,并没有完成数据渲染工作
//这里获取不到值,因为还没有完成渲染dom树工作
console.log("beforeMount:",document.getElementById("h1").innerText)
},
mounted:function () {
//第四个生命周期函数,这个函数执行时,vue已经完成template和el执行html渲染工作
//这里可以获取到值,
console.log("beforeMount:",document.getElementById("h1").innerText)
},
//运行阶段
beforeUpdate(){
//运行阶段第一个函数,这个函数执行时,data数据发生变化,此时页面数据还是原始数据
console.log("beforeUpdate data",this.msg)
console.log("beforeMount vive",document.getElementById("h1").innerText)
},
update(){
//运行阶段第二个函数,这个函数执行时,data数据页面数据保持一致
console.log("beforeUpdate data",this.msg)
console.log("beforeMount vive",document.getElementById("h1").innerText)
},
//销毁阶段
beforeDestroy(){
//销毁时第一个函数.这个函数执行时,vue实例刚刚开始销毁
console.log("开始销毁")
},
destroy(){
//最后一个函数
console.log("全部销毁成功")
}
})