建设手机网站哪个平台比较好,海外营销网站建设,wordpress 名片插件,网站后台批量上传图片118、ref引用
【1】JQuery里面的$(#app)。vue mv vm
【2】在vue中#xff0c;程序员不需要操作dom。程序员只需要维护好数据即可#xff08;数据驱动视图#xff09;。所以在vue下#xff0c;强烈不建议使用jquery#xff01;#xff01;#xff01;
【3】假…118、ref引用
【1】JQuery里面的$(#app)。vue mv vm
【2】在vue中程序员不需要操作dom。程序员只需要维护好数据即可数据驱动视图。所以在vue下强烈不建议使用jquery
【3】假设在vue项目中需要操作dom怎么办呢vue提供了ref在不依赖jquery的情况下获取dom。
!--第1部分--
templatedivh1 refref_h1App.vue父组件---{{countFromSon}}/h1 !----button clickshowThis打印this/button/div
/template!--第2部分--
script// 导入需要使用的组件/* import Left from /components/Left;import Right from /components/Right;*/export default {/* components: {Left,Right},*/data() {return {// 定义从子组件传值的属性countFromSon: 0}},methods: {showThis() {// console.log(this)this.$refs.ref_h1.style.color black // }}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style
****************************************************************************************************************************************************************************
119、使用ref引用组件实例
【1】感觉这种方式也可以用于父子兄弟传值呀.... 卧槽这个方案最简单的呀from老师的透露
【2】Left.vue
templatediv我是Left.vue子组件---{{count}}br/button clickcountcount1点击1/buttonbutton clickcount0重置/button/div
/templatescriptimport eventBus from /components/eventBus;export default {name: Left,data() {return {count: 0}},methods: {sendMsg() {// 通过eventBus发送数据eventBus.$emit(sendMsgToBrotherRight, this.msg)}}}
/scriptstyle scoped.box {background-color: yellow;}
/style
【3】App.vue
!--第1部分--
templatedivh1App.vue父组件/h1button clickshowThis打印this/buttonbutton clickreset重置Left组件的count/buttonLeft refrefLeft/Left/div
/template!--第2部分--
script// 导入需要使用的组件import Left from /components/Left;import Right from /components/Right;export default {components: {Left,Right},data() {return {name: 陈翔}},methods: {showThis() {console.log(this)},reset() {this.$refs.refLeft.count 0}}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style ****************************************************************************************************************************************************************************
120、初步实现按钮与文本框依次展示
【1】实现切换
!--第1部分--
templatedivh1App.vue父组件/h1hr/input typetext v-ifvisFlag blurshowButton/button clickshowInput v-else展示输入框/button/div/template!--第2部分--
script// 导入需要使用的组件import Left from /components/Left;import Right from /components/Right;export default {components: {Left,Right},data() {return {// 控制输入框与按钮展示切换visFlag: false}},methods: {showThis() {console.log(this)},reset() {this.$refs.refLeft.count 0},showInput() {this.visFlag true},showButton() {this.visFlag false}}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style
【2】解决input不自动获取焦点问题。updated不行因为当隐藏input的时候refInput还是未定义会报错。感觉也可以使用v-show我真是个天才呀。
!--第1部分--
templatedivh1App.vue父组件/h1hr/input typetext v-ifvisFlag blurshowButton refrefInput/button clickshowInput v-else展示输入框/button/div/template!--第2部分--
script// 导入需要使用的组件import Left from /components/Left;import Right from /components/Right;export default {components: {Left,Right},data() {return {// 控制输入框与按钮展示切换visFlag: false}},methods: {showThis() {console.log(this)},reset() {this.$refs.refLeft.count 0},showInput() {this.visFlag true// Cannot read properties of undefined (reading focus) 报错是因为还没有updated完毕/* console.log(this.$refs.refInput)this.$refs.refInput.focus()*/// 用到了延迟cb调用this.$nextTick(() { // 需要dom渲染完毕后 执行 就是延迟执行。this.$refs.refInput.focus() // })},showButton() {this.visFlag false}}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style
****************************************************************************************************************************************************************************
123、购物车案例-some循环
【1】主要是解决forEach的全部循环问题
!--第1部分--
templatedivh1App.vue父组件/h1/div/template!--第2部分--
script// 导入需要使用的组件export default {name: App,data() {return {// 控制输入框与按钮展示切换myArray: [小红, 倪大红, 苏大强, 宝贝]}},created() {/* this.myArray.forEach((item, index) {console.log(OK) // 打印4次说明性能浪费一直执行return没用 。一旦开始 无法在中间停止if (item 小红) {console.log(找到的索引位置为 index)return}})*/this.myArray.some((item, index) {console.log(OK)if (item 小红) {console.log(找到的索引位置为 index)return true // 通过return true 可以终止循环 固定写法}})},methods: {}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style ****************************************************************************************************************************************************************************
124、every循环
【1】都是true就返回true有一项是false则返回false
!--第1部分--
templatedivh1App.vue父组件/h1/div/template!--第2部分--
script// 导入需要使用的组件export default {name: App,data() {return {// 控制输入框与按钮展示切换myArray: [{id: 1, name: 西瓜, state: true},{id: 2, name: 橙子, state: true},{id: 3, name: 操作, state: false}]}},created() {const res this.myArray.every(item item.state)console.log(res)},methods: {}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style
****************************************************************************************************************************************************************************
125、reduce方法的使用
【1】普通用法
!--第1部分--
templatedivh1App.vue父组件/h1/div/template!--第2部分--
script// 导入需要使用的组件export default {name: App,data() {return {// 控制输入框与按钮展示切换myArray: [{id: 1, name: 西瓜, state: true, price: 10, count: 1},{id: 2, name: 橙子, state: true, price: 20, count: 2},{id: 3, name: 操作, state: false, price: 30, count: 3}]}},created() {let totalPrice 0; // 总价this.myArray.filter(item item.state).forEach(item {totalPrice totalPrice item.price * item.count})console.log(totalPrice)},methods: {}}
/script!--第3部分--
style.box {background-color: pink;border: 3px solid black;h1 {color: red;}}
/style
【2】高级用法created() {// let totalPrice 0; // 总价const res this.myArray.filter(item item.state).reduce((totalPrice, item) {return totalPrice totalPrice item.price * item.count}, 0)console.log(res)} ****************************************************************************************************************************************************************************
126、reduce的简化写法
【1】缩写版const res this.myArray.filter(item item.state).reduce((totalPrice, item) totalPrice totalPrice item.price * item.count, 0)console.log(res)
****************************************************************************************************************************************************************************
127、购入车案例
【1】git ee网址可以下载优秀的项目天下武功唯快不破。想让自己厉害现在厉害的项目做起。 ****************************************************************************************************************************************************************************
128、发起axios请求
【1】async function(){...await}
【2】在created调用initCartList方法created() {this.initCartList();console.log()} ****************************************************************************************************************************************************************************
129、请求回来的数据存到data里面去
【1】请求数据在页面要用的必须转存到data中。
【2】此list数据就是转存到data里定义的list数据。
****************************************************************************************************************************************************************************
130、渲染Goods列表
【1】在App里面引用Goods然后使用v-foritem in list循环展示 ****************************************************************************************************************************************************************************
131、为Goods组件封装属性
【1】:goodsNameitem.goods_name把App拿到的item属性传递给Goods组件使用。
【2】思路父组件向子组件传值。包括名称、图片、价格等属性 ****************************************************************************************************************************************************************************
132、Goods组件封装
【1】状态的封装
****************************************************************************************************************************************************************************
133、分析封装props
【1】:goodsitem 这是面向对象的思想厉害 厉害 厉害goods: {type: Object,default: {}}
【2】假如有个商品列表页面{id,title,price,image}、促销商品列表页面{id,title,x_price,x_image}。如果用面向对象的思想在Goods.vue就不能做兼容处理了
【3】所以还是需要分开接受属性我的哥哥呀。还得是老师分开的对。解决了是用goods.price还是goods.x_price呢所以还是得分开写。提升了复用性。 ****************************************************************************************************************************************************************************
134、如何修改商品
【1】change 只要复选框勾选状态发生变化会自动触发change函数 changesonStateChange/*勾选框状态改变触发的函数* 注意e 就是子组件通过$emit传递到父组件中的数据格式为{id,value}*/sonStateChange(e) {const newState e.target.checked; // 拿到最新状态this.$emit(son-fatherStateChange, { // 以此名称为准id: this.id,value: newState,});},
【2】Goods son-fatherStateChangefatherStateChange/Goods
fatherStateChange(e) {this.list.some((item) {if (item.id e.id) {item.goods_state e.value;return true;}});},
****************************************************************************************************************************************************************************
136、修改对应商品的状态
【1】使用some即可fatherStateChange(e) {/*根据子组件传的id value修改list里面的数据*/this.list.some((item) {if (item.id e.id) {item.goods_state e.value;return true;}});}, ****************************************************************************************************************************************************************************
137、定义fullState
【1】使用every即可// 动态计算全选状态fullState() {return this.list.every((item) item.goods_state);},
【2】自学能力、调试BUG能力、学习分析解决问题的能力。
【3】state是true还是false就决定是否全选了。
!--底部组件 state就是全选的标记--Footer:statefullStateisFullgetState:amounttotalAmount:totalPricetotalPrice/Footer
【4】又是一轮子传父 Footer.vue---App.vue
input typecheckbox idallCheck :checkedstate changegetState/
********************************************************************************************getState(e) {this.$emit(sonFatherIsFull, e.target.checked)}
********************************************************************************************/*全选按钮的切换*/getState(val) {this.list.forEach((item) {item.goods_state val;});},
【5】父传子---子传父
****************************************************************************************************************************************************************************
140、总数量、价格的计算
【1】App的computed计算属性里面/*已勾选商品的数量*/totalAmount() {return this.list.filter((item) item.goods_state).reduce((amount, item) (amount item.goods_count), 0);},
***************************************************************先指令后函数绑定
Footer:statefullState:amounttotalAmount:totalPricetotalPricesonFatherIsFullgetState/Footer
【2】也是App的computed计算属性里面
【3】父传子---子再传子...
****************************************************************************************************************************************************************************
142、发送给App.vue
【1】发现一个问题Counter---Goods---App传两次太麻烦了...不如都在App.vue中引用这样最多就是父子关系对吧。App.vue是所有的父其他的都是子。Goodsv-foritem in list:keyitem.id:goodsNameitem.goods_name:goodsPriceitem.goods_price:imgUrlitem.goods_img:goodsStateitem.goods_state:iditem.idson-fatherStateChangefatherStateChange!--商品的数量--Counter:counter_goodsCountitem.goods_countamount-changegetNewAmount(item, $event)/Counter/Goods
*********************************************************************************/*最新商品数量*/getNewAmount(item, e) {console.log(e)item.goods_count e;},
【2】学好Vue先给用组件名_变量名的形式规范定义变量。难度将会大大降低改完后看着舒服多了。
templatediv idappHeader/Header!--循环渲染Goods--Goodsv-foritem in list:keyitem.id:Goods_goodsNameitem.goods_name:Goods_goodsPriceitem.goods_price:Goods_imgUrlitem.goods_img:Goods_goodsStateitem.goods_state:Goods_iditem.idGoods_sonFatherStateChangeGoods_sonFatherStateChange!--商品的数量--Counter:Counter_goodsCountitem.goods_countamount-changegetNewAmount(item, $event)/Counter/Goods!--底部组件 state就是全选的标记--Footer:Footer_statefullState:Footer_amounttotalAmount:Footer_totalPricetotalPriceFooter_sonFatherIsFullFooter_sonFatherIsFull/Footer/div
/templatescriptimport Header from /components/Header;import Goods from /components/Goods;import Footer from /components/Footer;import axios from axios;import Counter from /components/Counter;export default {name: App,data() {return {list: [],};},components: {Header,Goods,Counter,Footer,},methods: {// 封装请求列表数据方法async initCartList() {// 结构data后重命名为resconst {data: res} await axios.get(https://www.escook.cn/api/cart);if (res.status 200) {this.list res.list;console.log(res.list);}},Goods_sonFatherStateChange(e) {/*根据子组件传的id value修改list里面的数据*/this.list.some((item) {if (item.id e.id) {item.goods_state e.value;return true;}});},/*全选按钮的切换*/Footer_sonFatherIsFull(val) {this.list.forEach((item) {item.goods_state val;});},/*最新商品数量*/getNewAmount(item, e) {console.log(JSON.stringify(item) e)item.goods_count e;},},created() {this.initCartList();console.log()},computed: {// 动态计算全选状态fullState() {return this.list.every((item) item.goods_state);},/*已勾选商品的价格*/totalAmount() {return this.list.filter((item) item.goods_state).reduce((amount, item) (amount item.goods_count), 0);},totalPrice() {return this.list.filter((item) item.goods_state).reduce((totalPrice, item) (totalPrice item.goods_count * item.goods_price),0);},},};
/scriptstyle langless
/style
****************************************************************************************************************************************************************************
144、动态计算已勾选的商品
【1】越看越知道规范命名的重要性一是规范命名二是命名能起到区分的作用才最重要的。
【2】南朝四百八十寺多少楼台烟雨中
****************************************************************************************************************************************************************************
145、课程概述
【1】动态组件、插槽、自定义指令没必要吧
****************************************************************************************************************************************************************************
146、动态组件
【1】控制多个组件的隐藏与展示
【2】component组件专门实现动态组件的渲染
【3】is属性的值就是渲染组件的名字。:iscomName 动态绑定属性的值。
templatedivh1App根组件/h1!--动态组件渲染--component :iscomName/component/div
/templatescriptimport Left from /components/Left;import Right from /components/Right;export default {name: App,data() {return {comName: Left};},components: {Left,Right},methods: {}};
/scriptstyle
/style
****************************************************************************************************************************************************************************
147、动态切换组件的展示
【1】动态修改属性的值而已
templatedivh1App根组件/h1button clickcomNameLeft展示 Left/buttonbutton clickcomNameRight展示 Right/button!--动态组件渲染--component :iscomName/component/div
/templatescriptimport Left from /components/Left;import Right from /components/Right;export default {name: App,data() {return {comName: Left};},components: {Left,Right},methods: {}};
/scriptstyle
/style
****************************************************************************************************************************************************************************
148、keep-alive的使用
【1】如果Left组件有个自增函数但当切换Right后再切回Left会发现left组件重新初始化了值也变为了0。
h3Left组件---{{count}}/h3
button clickcountcount1点击1/button
*********************************************************************
templatedivh3Left组件---{{count}}/h3button clickcountcount1点击1/button/div
/templatescriptexport default {name: Left,data() {return {count: 0}},created() {console.log(Left创建)},destroyed() {console.log(Left销毁)}}
/scriptstyle scoped.box {background-color: yellow;}
/style
【2】让离开时不被销毁包一层keep-alive即可。可以把内部的组件进行缓存而不是销毁。!--动态组件渲染--keep-alivecomponent :iscomName/component/keep-alive
****************************************************************************************************************************************************************************
149、keep-alive组件指定
【1】include属性通过includeLeft,Another只会缓存Left与Another多个用逗号间隔。!--动态组件渲染--keep-alive includeLeft,Anothercomponent :iscomName/component/keep-alive
【2】exclude代表排除组件。但是不能与include同时使用。 ****************************************************************************************************************************************************************************
150、组件注册名称
【1】如果在声明组件时没有为组件指定name名称则组件名称默认就是注册时名称。
【2】默认的都是使用默认与组件名一样的名称。
****************************************************************************************************************************************************************************
151、插槽
【1】是vue为组件封装者提供的能力一般开发用不到。
【2】slot/slot占位标签。小霸王游戏机的插槽来插卡插什么样的卡就是什么样的游戏
templatedivh3Left组件---{{count}}/h3!--声明一个插槽--slot/slot/div
/templatescriptexport default {name: Left,data() {return {count: 0}},created() {console.log(Left创建)},destroyed() {console.log(Left销毁)}}
/scriptstyle scoped.box {background-color: yellow;}
/style
***********************************************************
templatedivh1App根组件/h1Left这是用来填充Left插槽的.../Left/div
/templatescriptimport Left from /components/Left;import Right from /components/Right;export default {name: App,data() {return {comName: Left};},components: {Left,Right},methods: {}};
/scriptstyle
/style
****************************************************************************************************************************************************************************
152、v-slot指令
【1】slot/slot默认的namedefault
slot namedefault/slot
【2】指定插槽的名称放置内容。template只起到包裹作用不是真正的标签。Lefttemplate v-slot:default // span这是用来填充Left插槽的.../span/template/Left
【3】 v-slot:default必须用在template标签上不能用在普通元素标签上。 ****************************************************************************************************************************************************************************
153、v-slot的简写形式
【1】v-slot:简写是#
【2】插槽的默认内容指定
templatediv classboxh3Left组件---{{count}}/h3!--声明一个插槽--slot namedefault这是名字为default的slot ...默认的/slot/div
/template
****************************************************************************************************************************************************************************
154、具名插槽的定义与使用
【1】Vant组件库。插槽的一一定义与对应的一一使用。
templatediv!--标题--divslot nametitle/slot/div!--内容--divslot namecontent/slot/div!--作者--divslot nameauthor/slot/div/div
/templatescriptexport default {name: Article}
/scriptstyle scoped.article-container { div {min-height: 150px;}.header-box {background-color: pink;}.content-box {background-color: lightblue;}.footer-box {background-color: lightcoral;}}
/style
【2】使用时一一对应
templatedivh1App根组件/h1Articletemplate #titlespan一首诗/span/templatetemplate #contentspan琴瑟无端五十铉一年一柱思华年/span/templatetemplate #authorspan李商隐/span/template/Article/div
/templatescriptimport Left from /components/Left;import Right from /components/Right;import Article from /components/Article;export default {name: App,data() {return {comName: Left};},components: {Left,Right,Article},methods: {}};
/scriptstyle
/style ****************************************************************************************************************************************************************************
155、作用域插槽的基本用法
【1】插槽里定义数据。加了属性的插槽就变成了作用域插槽。!--内容--div classcontent-boxslot namecontent msgHello Vue/slot/div
【2】父组件接收使用的是{}对象.属性就可以使用了。template #contentobjectspan琴瑟无端五十铉一年一柱思华年/span{{object.msg}}
/template
****************************************************************************************************************************************************************************
156、作用域插槽解构赋值
【1】作用域插槽
templatediv!--标题--divslot nametitle/slot/div!--内容--divslot namecontent msgHello Vue :useruser/slot/div!--作者--divslot nameauthor/slot/div/div
/templatescriptexport default {name: Article,data() {return {user: {name: 陈翔,age: 20}};},}
/scriptstyle scoped.article-container { div {min-height: 150px;}.header-box {background-color: pink;}.content-box {background-color: lightblue;}.footer-box {background-color: lightcoral;}}
/style
【2】解构msgtemplate #content{msg}span琴瑟无端五十铉一年一柱思华年/spanbr/{{msg}}
/template
【3】解构usertemplate #content{user}span琴瑟无端五十铉一年一柱思华年/spanbr/{{user}}
/template
【4】同时结构
template #content{msg,user}span琴瑟无端五十铉一年一柱思华年/spanbr/{{msg}} {{user}}
/template ****************************************************************************************************************************************************************************
157、基于slot插槽购物车重构
【1】功能一定好好测试确实容易漏问题人非圣贤孰能无过。定义插槽div classgoods_padiv classprice{{ Goods_goodsPrice }}/divslot/slot/div
【2】使用插槽。Counter:Counter_goodsCountitem.goods_countamount-changegetNewAmount(item, $event)
/Counter
****************************************************************************************************************************************************************************
160、私有自定义指令
【1】定义名字为color的指令指向一个配置对象h1 v-colorApp根组件/h1*************************************directives: {color: {}},
*******************************************h1哪个元素绑定哪个元素变红
templatedivh1 v-colorApp根组件/h1Articletemplate #titlespan一首诗/span/templatetemplate #content{msg,user}span琴瑟无端五十铉一年一柱思华年/spanbr/{{msg}} {{user}}/templatetemplate #authorspan李商隐/span/template/Article/div
/templatescriptimport Left from /components/Left;import Right from /components/Right;import Article from /components/Article;export default {name: App,components: {Left,Right,Article},directives: {color: {/*当指令第一次被绑定到元素上的时候会立即触发bind函数*/bind(el) {console.log(触发v-color的bind函数...)el.style.color red}}},methods: {}};
/scriptstyle
/style ****************************************************************************************************************************************************************************
161、使用binding.value的值
【1】动态绑定data属性值。
h1 v-colorcolorApp根组件/h1
**************************************************data() {return {color: green}},directives: {color: {/*当指令第一次被绑定到元素上的时候会立即触发bind函数*/bind(el, binding) {console.log(触发v-color的bind函数... JSON.stringify(binding))el.style.color binding.value}}},
***********************************************************这种传字符串的用法也可以
h2 v-colorblackApp根组件/h2
****************************************************************************************************************************************************************************
162、自定义指令-update函数
【1】bind函数只会调用一次。更新则不会被执行
【2】 button clickcolorred改变 color 的颜色值/buttondata() {return {color: green}},directives: {color: {/*当指令第一次被绑定到元素上的时候会立即触发bind函数*/bind(el, binding) {console.log(触发v-color的bind函数... JSON.stringify(binding))el.style.color binding.value},/*定义update*/update(el, binding) {console.log(触发v-color的bind函数... JSON.stringify(binding))el.style.color binding.value}}}, ****************************************************************************************************************************************************************************
163、自定义指令的简写
【1】原来的 VS 简写
color: {/!*当指令第一次被绑定到元素上的时候会立即触发bind函数*!/bind(el, binding) {console.log(触发v-color的bind函数... JSON.stringify(binding))el.style.color binding.value},/!*定义update*!/update(el, binding) {console.log(触发v-color的bind函数... JSON.stringify(binding))el.style.color binding.value}}
****************************************************************************color(el, binding) {el.style.color binding.value}
****************************************************************************************************************************************************************************
164、全局自定义指令
【1】像定义全局过滤器一样。这样不管是App.vue还是Article.vue都能用了。
/*main.js*/
import Vue from vue
import App from ./App.vue
import axios from axiosVue.config.productionTip false
// 全局自定义指令
Vue.directive(color, function (el, binding) {el.style.color binding.value
})new Vue({render: h h(App),
}).$mount(#app) ****************************************************************************************************************************************************************************
165、main.js的小提示
【1】Vue.config.productionTip false /*控制台console能不能看到提示没有什么实际意义*/
****************************************************************************************************************************************************************************
166、eslint概述与作用
【1】约定代码风格。结尾要不要分号、缩进几个空格保证写出代码的风格几乎是完全一样的。一开始用会比较难。
【2】WebStorm设置File---Settings---Editor-code style --- javascript
【3】no-console... no-debugger
【4】常用的eslint的语法名字后面少一个空格。/**/前后强制使用一样的间距。
【5】vscode配置eslint ****************************************************************************************************************************************************************************
172、axios 的基本用法
【1】npm i axios -S
templatedivh3Left组件---/h3button clickgetInfo发起GET请求/button/div
/templatescriptimport axios from axiosexport default {name: Left,data() {return {count: 0}},methods: {async getInfo() {const {data} await axios.get(http://localhost:8002/login);console.log(data)}}}
/scriptstyle scoped.left-container {background-color: orange;min-height: 200px;flex: 1;}
/style
【2】发起post请求
templatedivh3Right组件/h3button clickpostInfo发起POST请求/button/div
/templatescriptimport axios from axiosexport default {name: Right,methods: {async postInfo() {const {data} await axios.post(http://localhost:8002/login)console.log(data)}}}
/scriptstyle scoped.right-container {background-color: lightblue;min-height: 200px;flex: 1;}
/style
****************************************************************************************************************************************************************************
173、把axios挂载到vue
【1】挂载到Vue原型属性
/*main.js*/
import Vue from vue
import App from ./App.vue
import axios from axiosVue.config.productionTip false /*控制台console能不能看到提示没有什么实际意义*/
// 全局自定义指令
Vue.directive(color, function (el, binding) {el.style.color binding.value
})
// 挂载axios
Vue.prototype.axios axiosnew Vue({render: h h(App),
}).$mount(#app)
【2】const {data} await this.axios.get(http://localhost:8002/login);使用不需要import操作了。
【3】后端路径优化操作还是挂原型。这个比青戈讲的透彻呀。
// 挂载axios
axios.defaults.baseURL http://localhost:8002 //
Vue.prototype.axios axios ****************************************************************************************************************************************************************************
174、axios不利于API接口的复用。
【1】它无法实现API接口的复用。每次调用都需要重新写请求方法与请求参数。
【2】所以还有优化的空间。
****************************************************************************************************************************************************************************
175、路由的概念
【1】英文router就是对应关系。SPA单页面应用程序。
【2】前端里路由就是Hash地址就是页面与地址的对应关系。 ****************************************************************************************************************************************************************************
176、路由的工作方式
【1】点击路由链接---导致URL地址栏中Hash值发生变化---前端路由监听变化---Hash地址对应组件渲染到浏览器中。
****************************************************************************************************************************************************************************
178、路由的基本用法
【1】vue-router路由包只能在vue项目使用。注意看官方文档。
【2】使用
*********************************************安装vue-router包
npm i vue-router3.5.2 -S
*********************************************创建路由模块.js文件
src/router/index.js
*********************************************导入挂载
/*index.js路由模块*/
// 导入
import Vue from vue;
import VueRouter from vue-router;
// 调用
Vue.use(VueRouter)
// 创建路由实例对象
const router new VueRouter()
// 向外共享路由实例对象
export default router
*********************************************声明路由和占位符
/*main.js*/
import Vue from vue
import App from ./App.vue
import axios from axios
import myRouter from ./router/index.js // 导入路由模块拿到路由的实例对象Vue.config.productionTip false /*控制台console能不能看到提示没有什么实际意义*/
// 全局自定义指令
Vue.directive(color, function (el, binding) {el.style.color binding.value
})
// 挂载axios
axios.defaults.baseURL http://localhost:8002
Vue.prototype.axios axiosnew Vue({render: h h(App),router: myRouter
}).$mount(#app) ****************************************************************************************************************************************************************************
179、基本用法-注意点
【1】import myRouter from ./router/index.js 可以写成import myRouter from ./router
【2】说明如果给定的是文件夹则默认是文件夹下面的index.js文件
****************************************************************************************************************************************************************************
180、路由模块基本用法、
【1】App中使用
templatedivh1App组件/h1hr/a href#/home首页/aa href#/movie电影/aa href#/about关于/ahr/!--只要在main.js配置了vue-router则·可以使用router-view--router-view/router-view/div
/templatescriptexport default {name: App,};
/scriptstyle scoped.box {display: flex;}
/style
【2】index.js定义Hash与页面的对应关系
/*路由模块*/
// 导入
import Vue from vue;
import VueRouter from vue-router;
import Home from /components/Home;
import Move from /components/Movie;
import About from /components/About;// 调用
Vue.use(VueRouter)// 创建路由实例对象
const router new VueRouter({// routers是一个数组是来定义hash地址与组件间的对应关系的。routes: [ // 注意不是routers{path: /home, component: Home},{path: /movie, component: Move},{path: /about, component: About},]
})// 向外共享路由实例对象
export default router ****************************************************************************************************************************************************************************
181、路由基本用法
【1】下面的就是叫做“路由规则”routes: [{path: /home, component: Home},{path: /movie, component: Move},{path: /about, component: About},]
【2】router-link就是用来替换a标签的
!-- a href#/home首页/aa href#/movie电影/aa href#/about关于/a--!--安装与配置了vue-router后可以用router-link来替换普通的链接了--router-link to/home首页/router-linkrouter-link to/movie电影/router-linkrouter-link to/about关于/router-link
【3】路由的重定向。解决访问localhost:8080能直接访问home页面而不是空页面routes: [{path: /, redirect: /home},/*重定向到home*/{path: /home, component: Home},{path: /movie, component: Move},{path: /about, component: About},]
****************************************************************************************************************************************************************************
183、嵌套路由
【1】套娃{path: /about,component: About,children: [{path: /left, component: Left},{path: /right, component: Right},]},
**********************************************************
templatediv classabout-containerh3About组件/h3hr/router-link to/leftLeft组件/router-linkrouter-link to/rightRight组件/router-linkhr/router-view/router-view/div
/template
****************************************************************************************************************************************************************************
185、嵌套路由-默认子路由
【1】子路由一般不写/
router-link to/about/leftLeft组件/router-link
router-link to/about/rightRight组件/router-link
【2】子路由一般不写/{path: /about,component: About,redirect: /about/left, // 默认子路由页面children: [//需要注意的是子路由规则不要以/开头{path: left, component: Left},{path: right, component: Right}]}
【3】完整路由
/*路由模块*/
// 导入
import Vue from vue;
import VueRouter from vue-router;
import Home from /components/Home;
import Move from /components/Movie;
import About from /components/About;
import Left from /components/Left;
import Right from /components/Right;// 调用
Vue.use(VueRouter)// 创建路由实例对象
const router new VueRouter({// routers是一个数组是来定义hash地址与组件间的对应关系的。routes: [{path: /, redirect: /home},/*重定向到home*/{path: /home, component: Home},{path: /movie, component: Move},{path: /about,component: About,redirect: /about/left,children: [//需要注意的是子路由规则不要以/开头{path: left, component: Left},{path: right, component: Right}]},]
})// 向外共享路由实例对象
export default router ****************************************************************************************************************************************************************************
186、动态路由匹配
【1】/mv/1 /mv/2 /mv/3不同的短片mv怎么定向
【2】使用英文的冒号: 可以指定动态路由项目。{path: /movie/:id, component: Move},
【3】这样电影1-5都能匹配到Move组件。
router-link to/home首页/router-link
router-link to/movie/1电影1/router-link
router-link to/movie/2电影2/router-link
router-link to/movie/3电影3/router-link
router-link to/movie/4电影4/router-link
router-link to/movie/5电影5/router-link
【4】需求Move组件中需要根据id的值来展示对应电影的详情信息。还可以写成 span获取到的id的值为{{$route.params.id}}/span
templatediv classmovie-containerh3Movie组件/h3!--button clickprintThis打印/button--span获取到的id的值为{{this.$route.params.id}}/span /div
/templatescriptexport default {name: Move}
/scriptstyle scoped/style
****************************************************************************************************************************************************************************
187、动态路由-开启props
【1】this.$route是路由的参数对象。this.$router是路由的导航对象。
***************************************开启propsroutes: [{path: /, redirect: /home},/*重定向到home*/{path: /home, component: Home},{path: /movie/:id, component: Move, props: true}, // 必须开启{path: /about,component: About,redirect: /about/left,children: [//需要注意的是子路由规则不要以/开头{path: left, component: Left},{path: right, component: Right}]},]
***************************************接收export default {name: Move,props: [id]}
***************************************使用
span获取到的id的值为{{this.$route.params.id}}---{{id}}/span
【2】props: true路由规则里有参数项必须指定。如果没有参数的就无需指定了。 ****************************************************************************************************************************************************************************
188、拓展query和fullPath
【1】/movie/2 斜线后面2这叫做路径参数。
*************************************************
$route.params.id通过这个来拿$route.params.xxx
【2】/movie/2?namezsage20 这种叫做查询参数
*************************************************
问号后面的参数项叫做查询参数
通过this.$route.query查询
*************************************************可以通过Movie.vue打印this查看
templatediv classmovie-containerh3Movie组件/h3!--button clickprintThis打印/button--!--this.$route是路由的参数对象--span获取到的id的值为{{this.$route.params.id}}---{{id}}/spanbutton clickshowThis打印this/button/div
/templatescriptexport default {name: Move,props: [id],methods: {showThis() {console.log(this);}}}
/scriptstyle scoped/style
【2】通过打印this可以看到path为/movie/2。而fullPath为/movie/2?namezs。
****************************************************************************************************************************************************************************
189、编程式导航跳转-push、replace、go
【1】声明式导航点击标签的形式编程式导航js写代码实现的跳转
【2】vue-router提供了编程式导航push、replace、go
*********************************都是this.$router注意多个rpush 会增加一条历史记录
templatediv classhome-containerh3Home组件/h3hr/button clickgotoMovie1跳转到电影1页面/button/div
/templatescriptexport default {name: Home,methods: {gotoMovie1() {this.$router.push(/movie/1)}}}
/scriptstyle scoped/style
*********************************replace跳转指定hash地址并替换掉当前的历史记录
templatediv classhome-containerh3Home组件/h3hr/button clickpushMovie1push跳转到电影1页面/buttonbutton clickreplaceMovie1replace跳转到电影1页面/button/div
/templatescriptexport default {name: Home,methods: {pushMovie1() {this.$router.push(/movie/1)},replaceMovie1() {this.$router.replace(/movie/1)}}}
/scriptstyle scoped/style
******************************************************************go(数值n)
templatediv classmovie-containerh3Movie组件/h3!--button clickprintThis打印/button--!--this.$route是路由的参数对象--span获取到的id的值为{{this.$route.params.id}}---{{id}}/spanbutton clickshowThis打印this/buttonbutton clickgoBack回退/button/div
/templatescriptexport default {name: Move,props: [id],methods: {showThis() {console.log(this);},goBack() {this.$router.go(-1)}}}
/scriptstyle scoped/style
******************************************************************go的简洁用法
this.$router.back()
this.$router.forward() ****************************************************************************************************************************************************************************
190、导航守卫可以控制路由的访问权限
【1】比如需要token才能访问
Main—导航守卫检测是否登录—Login登录—Main后台主页
【2】全局前置守卫
******************************************************************
每次发生路由的导航跳转时都会触发全局前置守卫。因此全局前置守卫中程序
员可以对每个路由进行访问权限控制。
【3】守卫方法的3个形参to、from、next
******************************************************************router-index.js
// 为router声明全局前置导航守卫
// 发生路由跳转必然触发beforeEach指定的function回调
router.beforeEach(function (to, from, next) {// next() 不调用则所有的路由都被拦截不调谁都不能访问
})
******************************************************************
// 为router声明全局前置导航守卫
// 发生路由跳转必然触发beforeEach指定的function回调
router.beforeEach(function (to, from, next) {console.log(from) // 将要离开的console.log(to) // 将要访问的next()
})
****************************************************************************************************************************************************************************
191、导航守卫-next函数的三种调用方式
【1】如果有访问权限next() 直接放行
【2】如果没有访问权限强制用next(/Login)强制访问Login页面
【3】强制停留在当前页面next(false)
****************************************************************************************************************************************************************************
192、路由守卫-控制访问权限
【1】定义Login和Main的路由规则
*********************************************************************
// 创建路由实例对象
const router new VueRouter({// routers是一个数组是来定义hash地址与组件间的对应关系的。routes: [{path: /, redirect: /home},/*重定向到home*/{path: /home, component: Home},{path: /movie/:id, component: Move, props: true},{path: /about,component: About,redirect: /about/left,children: [//需要注意的是子路由规则不要以/开头{path: left, component: Left},{path: right, component: Right}]},{path: /login, component: Login},{path: /main, component: Main},]
})
*********************************************************************拦截判断
router.beforeEach(function (to, from, next) {// 拿到用户将要访问的hash地址如果等于/main 证明页面是需要登录才能访问的if (to.path /main) {const token localStorage.getItem(token)if (token) {next()} else {next(/login)}} else {next()}
})
*********************************************************************模拟登录
在LocalStorage下面的本地网址添加token 123然后再点击登录
****************************************************************************************************************************************************************************
193、VUE2.0实例-安装和配置路由
【1】npm i vue-router3.5.2 -S
**********************************************************路由的配置
Vue.use(VueRouter);
**********************************************************
import Vue from vue
import App from ./App.vue
import router from ./router// 导入样式
import ./assets/css/bootstrap.css
import ./index.cssVue.config.productionTip falsenew Vue({render: h h(App),router
}).$mount(#app)
****************************************************************************************************************************************************************************
194、基于路由渲染登录组件
【1】在router-index.js里配置路由跳转
********************************************************************//登录的路由规则上面导入{path: /login,component: Login,},
********************************************************************App.vue
template!-- 路由占位符 --router-view/router-view
/template
********************************************************************根路径重定向{path: /,redirect: /login,},
****************************************************************************************************************************************************************************
195、模拟登录
【1】登录的判断逻辑admin 123456
templatedivdiv!-- 头像区域 --div classtext-center avatar-boximg src../assets/logo.png classimg-thumbnail avatar alt//div!-- 表单区域 --div classform-login p-4!-- 登录名称 --div classform-group form-inlinelabel forusername登录名称/labelinput typetext classform-control ml-2 idusername placeholder请输入登录名称 autocompleteoffv-model.trimusername//div!-- 登录密码 --div classform-group form-inlinelabel forpassword登录密码/labelinput typepassword classform-control ml-2 idpassword placeholder请输入登录密码v-model.trimpassword//div!-- 登录和重置按钮 --div classform-group form-inline d-flex justify-content-endbutton typebutton classbtn btn-secondary mr-2 clickreset重置/buttonbutton typebutton classbtn btn-primary clicklogin登录/button/div/div/div/div
/templatescriptexport default {name: MyLogin,data() {return {username: ,password: }},methods: {reset() { //this.username this.password },login() { //if (this.username admin this.password 123456) {//存储tokenlocalStorage.setItem(token, kong xxx)//跳转 到后台主页this.$router.push(/home)} else {//登录失败localStorage.removeItem(token)}}}}
/scriptstyle scoped.login-container {background-color: #35495e;height: 100%;.login-box {width: 400px;height: 250px;background-color: #fff;border-radius: 3px;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);box-shadow: 0 0 6px rgba(255, 255, 255, 0.5);.form-login {position: absolute;bottom: 0;left: 0;width: 100%;box-sizing: border-box;}}}.form-control {flex: 1;}.avatar-box {position: absolute;width: 100%;top: -65px;left: 0;.avatar {width: 120px;height: 120px;border-radius: 50% !important;box-shadow: 0 0 6px #efefef;}}
/style ****************************************************************************************************************************************************************************
196、说明Token
【1】前缀带不带取决于后端服务器
****************************************************************************************************************************************************************************
197、实现后台主页的基础布局
【1】Home.vue
**************************************************************
templatediv!-- 头部区域 --MyHeader/MyHeader!-- 页面主体区域 --div!-- 左侧边栏 --MyAside/MyAside!-- 右侧内容主体区 --div!-- 路由占位符 --router-view/router-view/div/div/div
/template
【2】Header.vue
templatediv classlayout-header-container d-flex justify-content-between align-items-center p-3!-- 左侧 logo 和 标题区域 --div classlayout-header-left d-flex align-items-center user-select-none!-- logo --img src../../assets/heima.png alt!-- 标题 --h4 classlayout-header-left-title ml-3黑马后台管理系统/h4/div!-- 右侧按钮区域 --divbutton typebutton classbtn btn-light clicklogout退出登录/button/div/div
/templatescriptexport default {name: MyHeader,methods: {logout() {//清空tokenlocalStorage.removeItem(token)//跳转回登录页面this.$router.push(/login)}}}
/scriptstyle scoped.layout-header-container {height: 60px;border-bottom: 1px solid #eaeaea;}.layout-header-left-img {height: 50px;}
/style
【3】Aside.vue
templatediv!-- 左侧边栏列表 --ul classuser-select-none menuli!-- 子路由链接要以/开头 --router-link to/home/users用户管理/router-link/lilirouter-link to/home/rights权限管理/router-link/lilirouter-link to/home/goods商品管理/router-link/lilirouter-link to/home/orders订单管理/router-link/lilirouter-link to/home/settings系统设置/router-link/li/ul/div
/templatescriptexport default {name: MyAside}
/scriptstyle scoped.layout-aside-container {width: 250px;height: 100%;border-right: 1px solid #eaeaea;}.menu {list-style-type: none;padding: 0;.menu-item {line-height: 50px;font-weight: bold;font-size: 14px;font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif;:hover {background-color: #efefef;cursor: pointer;}a {display: block;color: black;padding-left: 30px;:hover {text-decoration: none;}}}}// 设置路由高亮效果.router-link-active {background-color: #efefef;box-sizing: border-box;position: relative;// 伪元素实现路由高亮效果::before {content: ;display: block;width: 4px;height: 100%;position: absolute;left: 0;top: 0;background-color: #42b983;}}
/style ****************************************************************************************************************************************************************************
199、实现子路由的嵌套展示
【1】具体的路由嵌套。
routes: [{path: /,redirect: /login,},//登录的路由规则上面导入{path: /login,component: Login,},//后台主页的路由规则{path: /Home,component: Home,redirect: /home/users,children: [//在router-link中需要写全/在子路由规则中子路由 / 不需要再写{path: users, component: Users},{path: rights, component: Rights},{path: goods, component: Goods},{path: orders, component: Orders},{path: settings, component: Settings},//用户详情页的路由规则 (只有在路由规则中可以出现冒号){path: userinfo/:id, component: UserDetail},//第21种方式users{path:users/:id,component:UserDetail},// 在userdetail中获取路径中的id值信息第二种方式//{path:userinfo/:id,component:UserDetail,props:true},]
****************************************************************************************************************************************************************************
200、点击进入用户详情页
【1】用户列表页面
templatediv!-- 标题 --h4用户管理/h4!-- 用户列表 --table classtable table-bordered table-striped table-hovertheadtrth#/thth姓名/thth年龄/thth头衔/thth操作/th/tr/theadtbodytr v-foritem in userlist :keyitem.idtd{{item.id}}/tdtd{{item.name}}/tdtd{{item.age}}/tdtd{{item.position}}/tdtda href# click.preventgotoDeatail(item.id)详情/a!-- 第21种方式 --!-- router-link :to/home/users/ item.id详情/router-link --/td/tr/tbody/table/div
/templatescriptexport default {name: MyUser,data() {return {// 用户列表数据userlist: [{id: 1, name: 嬴政, age: 18, position: 始皇帝},{id: 2, name: 李斯, age: 35, position: 丞相},{id: 3, name: 吕不韦, age: 50, position: 商人},{id: 4, name: 赵姬, age: 48, position: 王太后}]}},methods: {gotoDeatail(id) {this.$router.push(/home/userinfo/ id)}}}
/scriptstyle scoped/style
【2】用户详情页面
templatedivbutton typebutton classbtn btn-light btn-sm click$router.back()后退/button!-- 使用this.$route.params.id 获取路径中的id值信息第一种方式--h4用户详情 --- {{this.$route.params.id}}/h4!-- 第二种方式使用下面props属性赋值并在路由规则中props:true就可以直接使用id --!-- h4用户详情 --- {{id}}/h4 --/div
/templatescriptexport default {name: MyUserDetail,props: [id]}
/scriptstyle scoped/style ****************************************************************************************************************************************************************************
201、升级用户详情页的路由
【1】动态写id传递id参数gotoDetail(id) {this.$router.push(/home/userinfo/ id)
}
【2】详情页拿到id{{this.$route.params.id}}
****************************************************************************************************************************************************************************
202、路由path的注意点
【1】路由重定向{path: /Home,component: Home,redirect: /home/users,children: [//在router-link中需要写全/在子路由规则中子路由 / 不需要再写{path: users, component: Users},{path: rights, component: Rights},{path: goods, component: Goods},{path: orders, component: Orders},{path: settings, component: Settings},//用户详情页的路由规则 (只有在路由规则中可以出现冒号){path: userinfo/:id, component: UserDetail},//第21种方式users{path:users/:id,component:UserDetail},// 在userdetail中获取路径中的id值信息第二种方式//{path:userinfo/:id,component:UserDetail,props:true},]},【2】path后面不要跟大写字母这是约定 ****************************************************************************************************************************************************************************
203、如何控制页面的权限
【1】判断不需要权限的菜单集合
const pathArray[/home,/home/users];
if(pathArray.indexOf(to.path)!-1){走token判断
}else{不走token判断
}
****************************************************************************************************************************************************************************
204、黑白头条项目结构
【1】vue-router的版本很重要
npm i vue-router3.5.2 -S
******************************************************************
import Vue from vue
import VueRouter from vue-router// 1、把VueRouter安装为Vue的插件
Vue.use(VueRouter)// 2、路由规则数组
const routeArray []// 3、创建路由实例对象
const router new VueRouter({routes: routeArray
})// 4、导出路由实例对象
export default router
******************************************************************
import Vue from vue
import App from ./App.vue
import router from /routerVue.config.productionTip falsenew Vue({router,render: h h(App),
}).$mount(#app)
【2】说明从0敲才能学得会 ****************************************************************************************************************************************************************************
205、安装配置Vant组件库
【1】现成的组件库
npm i vantlatest-v2
*********************************************************************
import Vue from vue
import App from ./App.vue
import router from /router
// 导入并安装vant插件
import Vant from vant
import vant/lib/index.cssVue.use(Vant)Vue.config.productionTip falsenew Vue({router,render: h h(App),
}).$mount(#app)
*********************************************************************van-button typeprimary主要按钮/van-buttonvan-button typesuccess成功按钮/van-buttonvan-button typedefault默认按钮/van-buttonvan-button typewarning警告按钮/van-buttonvan-button typedanger危险按钮/van-button
****************************************************************************************************************************************************************************
206、初始化-使用Tabbar组件
【1】开启路由模式的tabBar
templatediv idapp!--路由占位符--!--tabBar--van-tabbar routevan-tabbar-item replace to/ iconhome-o首页/van-tabbar-itemvan-tabbar-item replace to/user iconuser-0我的/van-tabbar-item/van-tabbar/div
/templatescriptexport default {name: App}
/scriptstyle scoped
/style ****************************************************************************************************************************************************************************
207、通过路由展示对应页面
【1】你只管努力生活会给你惊喜
templatediv idapp!--路由占位符--router-view/router-view!--tabBar--van-tabbar routevan-tabbar-item iconhome-o to/首页/van-tabbar-itemvan-tabbar-item iconuser-o to/user我的/van-tabbar-item/van-tabbar/div
/templatescriptexport default {name: App}
/scriptstyle scoped
/style
************************************************************************************
import Vue from vue
import VueRouter from vue-router
import Home from /views/Home/Home;
import User from /views/User/User;// 1、把VueRouter安装为Vue的插件
Vue.use(VueRouter)// 2、路由规则数组
const routeArray [// 首页路由规则{path: /, component: Home},{path: /user, component: User}
]// 3、创建路由实例对象
const router new VueRouter({routes: routeArray
})// 4、导出路由实例对象
export default router
****************************************************************************************************************************************************************************
208、使用NavBar组件
【1】初步体验标题固定内容展示
templatediv!--头部区域--van-nav-bar title标题 fixed/h3aaa/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3zzz/h3/div
/templatescriptexport default {name: Home}
/scriptstyle scoped.home-container {padding: 46px 0 50px 0;}
/style ****************************************************************************************************************************************************************************
209、覆盖NavBar的默认样式
【1】会用到类选择器的知识
templatediv!--头部区域--van-nav-bar title黑马头条 fixed/h3aaa/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3h3xxx/h3/div
/templatescriptexport default {name: Home}
/scriptstyle scoped.home-container {padding: 46px 0 50px 0;.van-nav-bar {background-color: #007bff;}/deep/ .van-nav-bar__title {color: white;}}
/style
****************************************************************************************************************************************************************************
210、获取列表数据
【1】主要是API接口返回json数据结构概述 ****************************************************************************************************************************************************************************
211、封装utils目录下的方法
【1】配置axios
********************************************************************安装
npm i axios -S
********************************************************************src下创建utils
/*req.js*/
import axios from axios;// 创建req即为小的axios
const req axios.create({// 指定请求的根路径baseURL: https://www.escook.cn
})export default req
****************************************************************************************************************************************************************************
212、在Home组件封装方法
【1】async...await
*********************************************************注意get请求的传参created() {this.initList();},methods: {// 获取文章列表数据的方法async initList() {const {data: res} await req.get(/articles, {// 请求参数params: {_page: this.page,_limit: this.limit}})console.log(res);}} ****************************************************************************************************************************************************************************
213、封装articleAPI模块
【1】主要是每次拿数据的复用
/*文章相关的API都放在这个下面*/// 向外按需导出一个API函数
import req from /utils/req;export const getArticleListAPI function (_page, _limit) {// 返回了一个promise对象return req.get(/articles, {// 请求参数params: {_page: _page,_limit: _limit}})
}
【2】Home User多方调用import {getArticleListAPI} from /api/articleAPI.js// 获取文章列表数据的方法async initList() {const {data: res} await getArticleListAPI(this.page, this.limit);console.log(res);}
***************************************************************************************import {getArticleListAPI} from /api/articleAPI.js// 获取文章列表数据的方法async initList() {const {data: res} await getArticleListAPI(this.page, this.limit);console.log(res);}
【3】这才是axios的真正的用法法拉利开出法拉利的速度
****************************************************************************************************************************************************************************
214、封装ArticleInfo组件
【1】如果不是直接被路由到的组件就放到components文件夹下面
templatedivArticleInfo组件/div
/templatescriptexport default {name: ArticleInfo}
/scriptstyle scoped/style
************************************************************************************!--导入 注册 并使用ArticleInfo 组件--ArticleInfo v-foritem in articleList :keyitem.id/ArticleInfo
************************************************************************************components: { //注册组件ArticleInfo}, ****************************************************************************************************************************************************************************
215、升级ArticleInfo
【1】自定义属性。props: { // 自定义属性// 标题title: {type: String, default: },// 作者author: {type: String, default: },// 评论数 类型指向数组包含可能的类型即可。commentNum: {type: [Number, String], default: 0},time: {type: String, default: }}
【2】父组件传值
!--导入 注册 并使用ArticleInfo 组件--ArticleInfo v-foritem in articleList :keyitem.id:titleitem.title:authoritem.aut_name:commentNumitem.comm_count:timeitem.pubdate/ArticleInfo
【3】大写的可以改成连字符建议不使用也没关系
****************************************************************************************************************************************************************************
226、图片
【1】自定义图片对象属性// 图片cover: {type: Object, default: function () {return {cover: 0}}}
【2】v-if来展示1张还是3张图片img :srccover.images[0] v-ifcover.type1div v-ifcover.type3img :srccover.images[0]img :srccover.images[1]img :srccover.images[2]/div ****************************************************************************************************************************************************************************
227、上拉加载更多了解List组件
【1】List组件通过loading和finised两个变量控制加载状态
*****************************************************触发load把loading改为true
为true的时候不会反复调用load事件防止用户非法操作。
拿到数据后把loading的值改为false
*****************************************************finised用来标记是否还有更多数据
****************************************************************************************************************************************************************************
218、使用List组件
【1】真牛批大成若缺
templatediv!--头部区域--van-nav-bar title黑马头条 fixed/!--导入 注册 并使用ArticleInfo 组件--van-list v-model:loadingloading :finishedfinished finished-text没有更多了 loadonLoadArticleInfo v-foritem in articleList :keyitem.id:titleitem.title:authoritem.aut_name:commentNumitem.comm_count:timeitem.pubdate:coveritem.cover/ArticleInfo/van-list/div
/templatescriptimport {getArticleListAPI} from /api/articleAPI.js;import ArticleInfo from /components/Article/ArticleInfo;export default {name: Home,components: { //注册组件ArticleInfo},data() {return {page: 1,limit: 10,articleList: [],loading: true, // 是否正在加载下一页finished: false // 所有数据是否加载完毕}},created() {this.initList();},methods: {// 获取文章列表数据的方法async initList() {const {data: res} await getArticleListAPI(this.page, this.limit);// console.log(res);this.articleList [...this.articleList, ...res]; // 旧数据在前新数据在后this.loading false;if (res.length 0) { // 如果res为空 表示数据加载完毕this.finished true;}},onLoad() {console.log(触发load事件)// 页码值甲乙this.page;// 重新调用方法this.initList();}}}
/scriptstyle scoped.home-container {padding: 46px 0 50px 0;.van-nav-bar {background-color: #007bff;}/deep/ .van-nav-bar__title {color: white;}}
/style ****************************************************************************************************************************************************************************
220、实现下拉刷新功能
【1】下拉刷新牛批van-pull-refresh v-modelrefreshing refreshonRefresh***************************************************************************templatediv!--头部区域--van-nav-bar title黑马头条 fixed/!--导入 注册 并使用ArticleInfo 组件--van-pull-refresh v-modelrefreshing refreshonRefresh :disabledfinished!-- :disabledfinished控制加载完毕后的无效刷新--van-list v-model:loadingloading :finishedfinished finished-text没有更多了 loadonLoadArticleInfo v-foritem in articleList :keyitem.id:titleitem.title:authoritem.aut_name:commentNumitem.comm_count:timeitem.pubdate:coveritem.cover/ArticleInfo/van-list/van-pull-refresh/div
/templatescriptimport {getArticleListAPI} from /api/articleAPI.js;import ArticleInfo from /components/Article/ArticleInfo;export default {name: Home,components: { //注册组件ArticleInfo},data() {return {page: 1,limit: 10,articleList: [],loading: true, // 是否正在加载下一页finished: false, // 所有数据是否加载完毕refreshing: false}},created() {this.initList();},methods: {// 获取文章列表数据的方法async initList(refreshFlag) { // 封装的思想const {data: res} await getArticleListAPI(this.page, this.limit);// console.log(res);if (refreshFlag) { // 下拉刷新this.articleList [...res, ...this.articleList]; // 新在前this.refreshing false;} else {this.articleList [...this.articleList, ...res]; // 旧数据在前新数据在后this.loading false;}if (res.length 0) { // 如果res为空 表示数据加载完毕this.finished true;}},onLoad() {console.log(触发load事件)// 页码值加一this.page;// 重新调用方法this.initList(false);},onRefresh() { // 下拉刷新的处理函数console.log(触发了下拉刷新)this.page;// 头部拼接this.initList(true);}}}
/scriptstyle scoped.home-container {padding: 46px 0 50px 0;.van-nav-bar {background-color: #007bff;}/deep/ .van-nav-bar__title {color: white;}}
/style
****************************************************************************************************************************************************************************
221、Vant定制主题
【1】为了覆盖默认的less变量在main.js引入import vant/lib/index.less ****************************************************************************************************************************************************************************
222、覆盖主题变量
【1】修改样式变量但是每次都重启开发中不用这个。
// vue.config.js
module.exports {css: {loaderOptions: {less: {// 若 less-loader 版本小于 6.0请移除 lessOptions 这一级直接配置选项。lessOptions: {modifyVars: {// 直接覆盖变量nav-bar-background-color: orange,// 或者可以通过 less 文件覆盖文件路径为绝对路径// hack: true; import your-less-file-path.less;,},},},},},
};
【2】less是可编程的样式语言。
****************************************************************************************************************************************************************************
224、通过theme.less指定
【1】less文件
/*
theme.less
*/
blue: #007bff;
// 覆盖NavBar的less样式
nav-bar-background-color: blue;
nav-bar-title-text-color: white;
【2】less文件绝对路径指定
// vue.config.js
// webpack在进行打包的时候底层用到了node.js 因此在vue.config.js配置文件中可以导入并使用node.js中的核心模块
const path require(path)
const themePath path.join(__dirname, ./src/theme.less)module.exports {css: {loaderOptions: {less: {// 若 less-loader 版本小于 6.0请移除 lessOptions 这一级直接配置选项。lessOptions: {modifyVars: {// 直接覆盖变量// nav-bar-background-color: orange,// 或者可以通过 less 文件覆盖文件路径为绝对路径 这个修改就不用重启服务器hack: true; import ${themePath};,},},},},},
}; ****************************************************************************************************************************************************************************
225、最后
【1】在前后端分离的情况下。而在开发过程中我们常常需要在window系统下使用
Nginx作为Web服务器。
【2】安装完毕后启动后在html下面放dist就完事了
****************************************************************************************************************************************************************************
226、总结
【1】vue-cli创建与开发工程化的vue项目
【2】组件化的开发思想
【3】指令、插槽、侦听器、声明周期、通讯函数来完成开发
【4】axios封装请求API接口
【5】vue-router实现单页面应用程序开发
【6】使用Vant与Element UI
【7】vue-devtools调试自己的vue项目