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 标签定义一个模板的代码解构:

    2、使用 Vue.component 注册组件:
    // 这是定义的全局组件 Vue.component('mycom3', {template: '#tmpl' })

    注意: 从更抽象的角度来说,每个组件,就相当于是一个自定义的元素; 注意: 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!
    私有组件定义
    私有组件只能当前定义的 VM 实例中可以使用
    代码:
    Document - 锐客网
    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 - 锐客网
    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 的区别
    1. data 在组件中,要被定义成 function 并返回一个对象
    2. props 在组件中,要被定义成数组,其中,数组的值都是字符串名,表示父组件传递过来的数据;
    3. 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的存储,读取,删除

      推荐阅读