Vue|3、Vue 笔记(axios、Vue 动画、Vue 组件、使用 this.$refs 来获取元素和组件、Vue 组件中 data 和 props 的区别)
文章目录
-
- axios 的使用
-
- 1、axios 基本使用
- 2、vue 中的 axios
- Vue中的动画
-
- 1、使用过渡类名实现动画
- 2、可修改 v- 前缀
- 3、使用第三方类库实现动画
- 4、使用钩子函数实现小球的半场动画
- 5、列表动画
- Vue 组件
-
- 定义 Vue 组件
- 全局组件定义的三种方式
-
- 第一种方式:
- 第二种方式:
- 第三种方式:
- 私有组件定义
- 组件中展示数据和响应事件
- 组件切换
-
- 切换方式一(使用flag标识符结合v-if和v-else切换组件)
- 切换方式二(使用component标签的:is属性来切换组件,并添加动画)
- 组件切换时切换动画
- 父组件向子组件传值
- 父组件向子组件传递方法
- 组件案例-评论列表
- 使用 `this.$refs` 来获取元素和组件
-
- `ref` 介绍
- `this.$refs` 介绍
- 实例
- 在 Vue 组件中 data 和 props 的区别
- 补充(localStorage 本地存储)
axios 的使用
Axios 是一个基于 promise 网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和 node.js 中)。在服务端它使用原生 node.js http 模块, 而在客户端(浏览端)则使用XMLHttpRequests。1、axios 基本使用
axios 必须先导入才可以使用
使用 get 或 post 方法即可发送对应的请求
then 方法中的回调函数会在请求成功或失败时触发(成功是第一个,失败时第二个函数)
通过回调函数的形参可以获取响应内容,或错误信息
代码:
Document - 锐客网
src="https://unpkg.com/axios/dist/axios.min.js">
>
/*
接口1:随机笑话
请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num(笑话条数,数字)
响应内容:随机笑话
*/
document.querySelector(".get").onclick = function () {axios.get("https://autumnfish.cn/api/joke/list?num=3")
.then(function (response) {console.log(response);
}, function (err) {console.log(err);
})
}
/*
接口2:用户注册
请求地址:https://autumnfish.cn/api/user/reg
请求方法:post
请求参数:username(用户名,字符串)
响应内容:注册成功或失败*/
document.querySelector(".post").onclick = function () {axios.post("https://autumnfish.cn/api/user/reg", {
username: "jack" })
.then(function (response) {console.log(response);
}, function (err) {console.log(err);
})
}
2、vue 中的 axios
代码:
Document - 锐客网
{
{joke}}
src="https://unpkg.com/axios/dist/axios.min.js">
src=" https://cdn.staticfile.org/vue/2.2.2/vue.min.js">
>
/*
接口1:随机笑话
请求地址:https://autumnfish.cn/api/joke
请求方法:get
请求参数:无
响应内容:随机笑话
*/
var app = new Vue({el: "#app",
data: {joke: "joke"
},
methods: {getJoke: function () {console.log(this);
var that = this;
axios.get("https://autumnfish.cn/api/joke").then(
function (response) {// console.log(response);
console.log(response.data);
that.joke = response.data;
}, function (err) {console.log(err);
}
)
}
},
})
axios 回调函数中的 this 已经改变,无法访问到 data 中数据
把 this 保存起来,回调函数中直接使用保存的 this 即可
和本地应用的最大区别就是改变了数据来源
Vue中的动画 链接:Vue 动画
为什么要有动画:动画能够提高用户的体验,帮助用户更好的理解页面中的功能;1、使用过渡类名实现动画
代码:
Document - 锐客网 >
/* v-enter [这是一个时间点] 是进入之前,元素的起始状态,此时还没有开始进入 */
/* v-leave-to [这是一个时间点] 是动画离开之后,离开的终止状态,此时,元素动画已经结束了 */
.v-enter,
.v-leave-to {opacity: 0;
transform: translateX(150px);
}/* v-enter-active 【入场动画的时间段】 */
/* v-leave-active 【离场动画的时间段】 */
.v-enter-active,
.v-leave-active {transition: all 0.8s ease;
}
这是一个H3
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {flag: false
},
methods: {
}
});
2、可修改 v- 前缀
Document - 锐客网 >
/* v-enter [这是一个时间点] 是进入之前,元素的起始状态,此时还没有开始进入 */
/* v-leave-to [这是一个时间点] 是动画离开之后,离开的终止状态,此时,元素动画已经结束了 */
.v-enter,
.v-leave-to {opacity: 0;
transform: translateX(150px);
}/* v-enter-active 【入场动画的时间段】 */
/* v-leave-active 【离场动画的时间段】 */
.v-enter-active,
.v-leave-active {transition: all 0.8s ease;
}.my-enter,
.my-leave-to {opacity: 0;
transform: translateY(70px);
}.my-enter-active,
.my-leave-active {transition: all 0.8s ease;
}
这是一个H3
这是一个H6
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {flag: false,
flag2: false
},
methods: {
}
});
3、使用第三方类库实现动画
1)导入动画类库:
2)定义 transition 及属性:
这是一个H3
代码:
Document - 锐客网
这是一个H3
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {flag: false
},
methods: {
}
});
4、使用钩子函数实现小球的半场动画
代码:
Document - 锐客网
>
.ball {width: 15px;
height: 15px;
border-radius: 50%;
background-color: red;
}
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {flag: false
},
methods: {// 定义三个 methods 钩子方法:
// 注意: 动画钩子函数的第一个参数: el ,表示 要执行动画的那个 DOM 元素 是原生的JS DOM对象
// 大家可以认为 , el 是通过 document.getElementById('') 方式获取到的原生JS DOM 对象
beforeEnter(el) {// beforeEnter 表示动画入场之前,此时,动画尚未开始,可以在 beforeEnter 中,设置元素开始动画之前的起始样式
// 设置小球开始动画之前的,起始位置
el.style.transform = "translate(0,0)"
},
enter(el, done) {// 这句话,没有实际的作用,但是,如果不写,出不来动画效果
// 可以认为 el.offsetWidth 会强制动画刷新
el.offsetWidth
// enter 表示动画 开始之后的样式,这里,可以设置小球完成动画之后的 结束状态
el.style.transform = "translate(150px,450px)"
el.style.transition = "all 1s ease"// 这里的done,其实就是afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
done()
},
afterEnter(el) {// 动画完成之后,会调用 afterEnter
this.flag = !this.flag
}
}
});
5、列表动画
代码:
Document - 锐客网
>
li {border: 1px dashed #999;
margin: 5px;
line-height: 35px;
padding-left: 5px;
font-size: 12px;
width: 100%;
}li:hover {background-color: pink;
transition: all 0.6s ease;
}.v-enter,
.v-leave-to {opacity: 0;
transform: translateY(80px);
}.v-enter-active,
.v-leave-active {transition: all 0.6s ease;
}/* 下面的 .v-move 和 .v-leave-active 配合使用,能够实现列表后续元素,渐渐地飘上来的效果 */
.v-move {transition: all 0.6s ease;
}.v-leave-active {position: absolute;
}
{
{item.id}} --- {
{item.name}}
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {id: '',
name: '',
list: [
{
id: 1, name: '周哥' },
{
id: 2, name: '李哥' },
{
id: 3, name: '张哥' },
{
id: 4, name: '沈哥' }
]
},
methods: {add() {this.list.push({
id: this.id, name: this.name })
this.id = this.name = ''
},
del(i) {this.list.splice(i, 1)
}
}
});
Vue 组件 定义 Vue 组件
- 什么是模块化:模块化是从代码的角度出发,分析项目,把项目中一些功能类似的代码,单独的抽离为一个个的模块;那么为了保证大家以相同的方式去封装模块,于是我们就创造了模块化的规范(CommonJS规范);
- 模块化的好处:方便项目的开发;和后期的维护与扩展;今后如果需要某些固定功能的模块,则直接拿来引用就行,提高了项目开发效率!
- 什么是组件化:从UI的角度出发考虑问题,把页面上有重用性的UI解构和样式,单独的抽离出来,封装为单独的组件;
- 组件化的好处:随着项目规模的发展,我们手里的组件,会越来越多,这样,我们今后一个页面中的UI,几乎都可以从手中拿现成的组件拼接出来;方便项目的开发和维护;
第一种方式: 1、先调用 Vue.extend() 得到组件的构造函数:
// 创建全局组件的第一种方式:component
const com1 = Vue.extend({template: '这是创建的第一个全局组件' // template 属性,表示这个组件的 UI 代码解构
})
2、通过 Vue.component(‘组件的名称’, 组件的构造函数) 来注册全局组件:
// 使用 Vue.component 向全局注册一个组件
// Vue.component('组件的名称', 组件的构造函数)
Vue.component('mycom1', com1)
注意:
如果使用 Vue.component 定义全局组件的时候,组件名称使用了驼峰命名,则在引用组件的时候,需要把大写的驼峰改为小写的字母同时,两个单词之间,使用 - 链接以上两步可写为一步:
如果不使用驼峰,则直接拿名称来使用即可
Vue.component('myCom1', Vue.extend({template: '这是使用 Vue.extend 创建的组件
'
}))
3、把注册好的全局组件名称,以标签形式引入到页面中即可:
第二种方式: 直接使用 Vue.component(‘组件名称’, { 组件模板对象 })
const com2Obj = {// 1. template 属性中,不能单独放一段文本,必须用标签包裹起来;
// 2. 如果在 template 属性中,想要放多个元素了,那么,在这些元素外,必须有唯一的一个根元素进行包裹;
template: '这是直接使用 Vue.component 创建出来的组件红红火火
'
} // 定义全局的组件
// Vue.component 的第二个参数,既接收 一个 组件的构造函数, 同时,也接受 一个对象
Vue.component('mycom2', com2Obj)
或者:
Vue.component('mycom2', {// 注意: 不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素
template: '这是直接使用 Vue.component 创建出来的组件的组件
123'
})
第三种方式: 1、先使用 template 标签定义一个模板的代码解构:
哈哈,这是在外界定义的组件UI解构
我是来捣乱的
2、使用 Vue.component 注册组件:
// 这是定义的全局组件
Vue.component('mycom3', {template: '#tmpl'
})
注意: 从更抽象的角度来说,每个组件,就相当于是一个自定义的元素; 注意: 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!私有组件定义
私有组件只能当前定义的 VM 实例中可以使用
代码:
Document - 锐客网
这是私有的 login 组件
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {
},
methods: {
},
components: {
//定义实例内部私有组件
login: {template: "#tmpl2"
}
}
});
组件中展示数据和响应事件
1.组件可以有自己的 data 数据
2.组件的 data 和实例的 data 有点不一样,实例中的 data 可以为一个对象,但是组件中的 data 必须是一个方法
3.组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行
4.组件中的 data 数据使用方式,和实例中的 data 使用方式完全一样!!!
Vue.component('mycom1', {template: "这是全局组件 --- {
{ msg }}",
data: function () {return {msg: '这是组件中的data定义的数据'
}
}
})
计数器案例:
Document - 锐客网
{
{ count }}
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var dataObj = {
count: 0 }
// 这是一个计数器组件,身上有个按钮,每当点击按钮,让 data 中的 count 值 +1
Vue.component('counter', {template: '#tmpl',
data: function () {// return dataObj
return {
count: 0 }
},
methods: {increment() {this.count++
}
}
})var vm = new Vue({el: '#app',
data: {
},
methods: {
}
});
以上案例可以解释为什么 组件中的 data 必须是一个方法 以及 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行
“组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。”组件切换
切换方式一(使用flag标识符结合v-if和v-else切换组件) 代码:
Document - 锐客网
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
Vue.component('login', {template: '登录组件
'
})Vue.component('register', {template: '注册组件
'
})var vm = new Vue({el: '#app',
data: {flag: true
},
methods: {
}
});
切换方式二(使用component标签的:is属性来切换组件,并添加动画) 代码:
Document - 锐客网
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
// 组件名称是 字符串
Vue.component('login', {template: '登录组件
'
})Vue.component('register', {template: '注册组件
'
})var vm = new Vue({el: '#app',
data: {comName: 'login'//当前 component 中的 :is 绑定的组件名称
},
methods: {
}
});
组件切换时切换动画
代码:
Document - 锐客网
>
.v-enter,
.v-leave-to {opacity: 0;
transform: translateX(150px);
}.v-enter-active,
.v-leave-active {transition: all 0.5s ease;
}
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
// 组件名称是 字符串
Vue.component('login', {template: '登录组件
'
})Vue.component('register', {template: '注册组件
'
})var vm = new Vue({el: '#app',
data: {comName: 'login'//当前 component 中的 :is 绑定的组件名称
},
methods: {
}
});
注意:通过 mode 属性,设置组件切换时候的模式 非常重要,可以使动画看起来非常流畅。
父组件向子组件传值
步骤:
1、把要传递给子组件的数据,作为 自定义属性,通过 v-bind: 绑定到子组件身上
2、在子组件中,不能直接使用父组件传递过来的数据,需要先使用 props 数组来接收一下
3、注意:在接收父组件传递过来的 props 的时候,接收的名称,一定要和父组件传递过来的自定义属性,名称保持一致!
代码:
Document - 锐客网
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var vm = new Vue({el: '#app',
data: {msg: '123 父组件中的数据'
},
methods: {
},
components: {// 结论: 经过演示,发现,子组件中,默认无法访问到 父组件中的data 上的数据 和methods 中的方法
com1: {data() {
//注意: 子组件中的data数据,并不是通过 父组件传递过来的,而是子组件自身私有的,
// 比如:子组件通过Ajax,请求回来的数据,都可以放到 data 身上
// data 上的数据,都是可读可写的
return {title: '123',
content: 'qqq'
}
},
template: '这是子组件 --- {
{ parentmsg }}',
// 注意: 组件中的 所有 props 中的数据,都是通过 父组件传递给 子组件的
// props 中的数据,都是只读的,无法重新赋值
props: ['parentmsg'],//把父组件传递过来的parentmsg 属性,现在props 数组中定义一下,这样才能使用这个数据
directives: {
},
filters: {
},
components: {
},
methods: {changed() {this.parentmsg = '被修改了'
}
},
}
}
});
父组件向子组件传递方法
组件向子组件 传递方法,使用的是 事件绑定机制,v-on,当我们自定义了 一个 事件属性之后,那么,子组件就能够,通过某些方式,来调用 传递进去的这个方法了
代码:
Document - 锐客网
这是 子组件
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>// 定义了一个字面量类型的 组件模板对象
var com2 = {template: '#tmpl',//通过指定一个Id,表示说,要去加载 这个指定Id的 template 元素中的内容,当做组件的HTML结构
data() {return {sonmsg: {
name: '小头儿子', age: 6 }
}
},
methods: {myclick() {// console.log('ok')
// 当点击 子组件 按钮的时候,如何拿到父组件 传递过来的 func 方法,并调用这个方法?
// emit 英文原意:是触发,调用,发射的意思
// this.$emit('func', 123, 456)
this.$emit('func', this.sonmsg)
}
},
}var vm = new Vue({el: '#app',
data: {datamsgFormSon: null
},
methods: {show(data) {// console.log('调用了父组件身上的 show 方法: --- ' + data)
console.log(data)
this.datamsgFormSon = data
}
},
components: {com2
}
});
更多组件之间的传值参考网站:子组件与父组件之间传值
组件案例-评论列表
分析:发表评论的业务逻辑代码:
1.评论的数据存到哪里去??? 存放到 localStorage 中
2.先组织出一个最新的评论数据对象
3.想办法,把第二步中得到的评论对象,保存到 localStorage 中
3.1 localStorage 只支持存放字符串对象,要先调用 JSON.stringify
3.2 在保存最新的评论数据之前,要先从 localStorage 获取之前的评论数据( string ),转化为 一个 数组对象
然后,把最新的评论,push 到这个数组
3.3 如果获取到的 localStorage 中的 评论字符串,为空不存在,则 可以 返回一个 ‘[]’ 让 JSON.parse 去转换
3.4 把 最新的评论列表数组,再次调用 JSON.stringify 转为 数组字符串,然后调用 localStorage.setItem()
Document - 锐客网
-
class="badge">评论人 : {
{ item.user }}
{
{ item.content }}
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>var commentBox = {data() {return {user: '',
content: ''
}
},
template: '#tmpl',
methods: {postComment() {
//发表评论的方法
// 分析:发表评论的业务逻辑
// 1.评论的数据存到哪里去??? 存放到 localStorage 中
// 2.先组织出一个最新的评论数据对象
// 3.想办法,把第二步中得到的评论对象,保存到 localStorage 中
// 3.1 localStorage 只支持存放字符串对象,要先调用 JSON.stringify
// 3.2 在保存最新的评论数据之前,要先从 localStorage 获取之前的评论数据( string ),转化为 一个 数组对象
//然后,把最新的评论,push 到这个数组
// 3.3 如果获取到的 localStorage 中的 评论字符串,为空不存在,则 可以 返回一个 '[]'让 JSON.parse 去转换
// 3.4 把 最新的评论列表数组,再次调用 JSON.stringify 转为 数组字符串,然后调用 localStorage.setItem()var comment = {
id: Date.now(), user: this.user, content: this.content }// 从 localStorage 中获取所有的评论
var list = JSON.parse(localStorage.getItem('cmts') || '[]')
list.unshift(comment)
// 重新保存最新的评论数据
localStorage.setItem('cmts', JSON.stringify(list))this.user = this.content = ''
// 子组件调用父组件方法
this.$emit('func')
}
},
}var vm = new Vue({el: '#app',
data: {list: [
{
id: Date.now(), user: '李白', content: '天生我材必有用' },
{
id: Date.now(), user: '小李白', content: '劝君更尽一杯酒' },
{
id: Date.now(), user: '小李', content: '小李飞刀' },
]
},
beforeCreate() {
// 注意:这里不能调用 loadComments 方法,因为在执行这个钩子函数的时候,data 和 methods 都还没有被初始化好},
created() {this.loadComments()
},
methods: {loadComments() {
//从本地的localStorage 中,加载评论列表
var list = JSON.parse(localStorage.getItem('cmts') || '[]')
this.list = list}
},
components: {'cmt-box': commentBox
}
});
使用
this.$refs
来获取元素和组件
ref
介绍ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的$refs
对象上。如果在普通的 DOM
元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向该子组件实例
通俗的讲,ref特性就是为元素或子组件赋予一个ID引用,通过this.$refs.refName
来访问元素或子组件的实例
this.$refs
介绍实例this.$refs
是一个对象,持有当前组件中注册过 ref 特性的所有 DOM 元素和子组件实例
注意: $refs只有在组件渲染完成后才填充,在初始渲染的时候不能访问它们,并且它是非响应式的,因此不能用它在模板中做数据绑定
Document - 锐客网
哈哈哈,今天天气真好!
src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">
>
var login = {template: '登录组件',
data() {return {msg: 'son msg'
}
},
methods: {show() {console.log('调用了子组件方法')
}
},
}var vm = new Vue({el: '#app',
data: {
},
methods: {getElement() {// console.log(document.getElementById('myh3').innerText)// ref 是英文单词 【reference】值类型 和 引用类型referenceError
// console.log(this.$refs.myh3.innerText)// console.log(this.$refs.mylogin.msg)
this.$refs.mylogin.show()
}
},
components: {login
}
});
在 Vue 组件中 data 和 props 的区别
- data 在组件中,要被定义成 function 并返回一个对象
- props 在组件中,要被定义成数组,其中,数组的值都是字符串名,表示父组件传递过来的数据;
- props 的数据,不要直接拿来修改,如果想要修改,必须在 data 上重新定义一个 属性,然后把属性的值 从 this.props 拿过来;
data 上的数据,都是组件自己私有的, data 上的数据,都是可读可写的 props 数据,都是外界传递过来的数据, props 中的数据只能读取,不能重新写入补充(localStorage 本地存储) localstorage 存储对象分为两种:
① sessionStrage: session 即会话的意思,在这里的 session 是指用户浏览某个网站时,从进入网站到关闭网站这个时间段,session 对象的有效期就只有这么长。
② localStorage: 将数据保存在客户端硬件设备上,不管它是什么,意思就是下次打开计算机时候数据还在。
两者区别就是一个作为临时保存,一个长期保存。
【Vue|3、Vue 笔记(axios、Vue 动画、Vue 组件、使用 this.$refs 来获取元素和组件、Vue 组件中 data 和 props 的区别)】localStorage 的存储,读取,删除方法
参考博客:localStorage的存储,读取,删除
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- Shell-Bash变量与运算符
- 清明,是追思、是传承、是感恩。
- 牛人进化+|牛人进化+ 按自己的意愿过一生
- vue-cli|vue-cli 3.x vue.config.js 配置
- 七老修复好敏感、角质层薄、红血丝
- 华为旁!大社区、地铁新盘,佳兆业城市广场五期!
- 2020-04-07vue中Axios的封装和API接口的管理