1、封装
- 1)在项目中导入
axios:npm i axios - 2)对于封装我们一般在项目的
src文件下 去创建一个plugins
// axios 封装
import axios from 'axios'
import Vue from 'vue'
const instance = axios.create({
// 请求基地址
baseURL: "http://localhost:3008/",
timeout: 2000 // 控制时间 2000 = 2s,
// 请求头的配置
// headers
})
// 请求拦截器
// 例:提示开会员
instance.interceptors.request.use((config) => {
// 请求头配置 config
// config.auth = 'token'
return config
})
// 响应拦截器
instance.interceptors.response.use((res) => {
return res.data
})
// vue 全局加上 $http
// 在组件中使用 this.$http 就相当于 instance 了
Vue.prototype.$http = instance
- 3)封装好了后,我们在父组件中去使用
<script>
export default {
async created() {
const res = await this.$http.get('/cart');
console.log(res);
}
}
</script>
并且在 main.js 中引入
import Vue from 'vue'
import App from './App.vue'
import './plugins/http' //引入 plugins 文件下的 http.js
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
2、 Vue 中的样式处理
- 1)可以直接在
style内添加scoped将组件样式变成私有化
<template>
<div class="cart-item">
...
<button class="del">删除</button>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
/* 样式的处理 */
/* 1.直接在 style 内添加 scoped 将组件样式变成私有化 */
/* scoprd 作用是给所在组件内的的标签 添加一个相同,但又与其他组件不同的属性 data-v-xxxxx */
/* 所有样式都会使用这个属性选择器来书写 */
.del {
color: red;
}
</style>
scoprd作用是给所在组件内的的标签 添加一个相同,但又与其他组件不同的属性data-v-xxxxx
所有样式都会使用这个属性选择器来书写

============================================================================
2.1高级 CSS 语法
css 预处理 css 控制语言 高级的 css 语法
因为:浏览器不支持高级的 css 语法解决方法安装相应的工具包
less 介绍以及安装
- Less (Leaner Style Sheets 的缩写) 是一门向后兼容的 CSS 扩展语言。
- 步骤一:首先需要安装对应的包
npm i less less-loader -D - 安装好后在:项目的
package.json查看对应的版本号

- 导入 less 语法
-
<style scoped lang='less'>...</style>
less 的使用方法
- 1)嵌套(Nesting)
- Less 提供了使用嵌套(nesting)代替层叠或与层叠结合使用的能力
- 可以根据结构将
.del与.cart-item .count input嵌套 到.cart-item中 - 滑过效果的写法:
&:hover{ colc:..}& 表示自己
老写法
<style scoped lang='less'>
.cart-item{
display: flex;
justify-content: space-between;
padding: 20px 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
align-items: flex-start;
}
.del {
color: red;
}
.del:hover {
color: aqua;
}
.cart-item .count input{
width: 40px;
}
</style>
新写法
<style scoped lang='less'>.cart-item{
display: flex;
justify-content: space-between;
padding: 20px 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
align-items: flex-start;
.count {
/* 在 input 前面可以写 + 号,> 号*/
input {
width: 40px;
}
}
.del {
color: red;
&:hover{
color: aqua;
}
}
</style>
============================================================================
- 2)运算(Operations)
- 在css中可以使用算术运算符
+、-、*、/可以对任何数字、颜色或变量进行运算。
<style scoped lang='less'>
.cart-item{
display: flex;
justify-content: space-between;
padding: 20px 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
align-items: flex-start;
.count {
input {
width: 30px +10 px; /* 宽度结果为40px */
}
}
.del {
color: red;
&:hover{
color: aqua;
}
}
}
</style>在这里插入代码片
============================================================================
- 3)变量(Variables)
@width: 10px;
@height: @width + 10px;
.header {
width: @width;
height: @height;
}
编译结果是;
.header {
width: 10px;
height: 20px;
}
============================================================================
- 4)混合(Mixins)
- 混合(Mixin)是一种将一组属性从一个规则集包含(或混入)到另一个规则集的方法
// 先定义
.border-top-bottom {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.cart-item{
...
/* 使用 */
.border-top-bottom ();
...
}
============================================================================
- 5)导入(Importing)
- 在assets创建一个
style.less文件 - 导入
style.less文件@import '../assets/style.less'; - 使用 语法:@定义名
@width:30px;
导入:@import '../assets/style.less';
使用:width: @width + 10px;
sass 介绍以及安装
- sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby。
- 步骤一:正常安装 sass 大概率会失败:
- 首先先执行:
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/ - 然后安装对应的包
npm i node-sass sass-loader -D - 安装好后在:项目的
package.json查看对应的版本号

- 导入 sass 语法
-
<<style lang="scss">...</style>
sass 的使用方法
- 1)嵌套(Nesting)
- css中重复写选择器是非常恼人的。如果要写一大串指向页面中同一块的样式时,往往需要 一遍又一遍地写同一个ID
老写法
<style lang="scss">
.cart{
width: 600px;
margin: 0 auto;
}
.cart-header .form-head{
display: flex;
justify-content: space-between;
}
.cart .cart-footer {
display: flex;
justify-content: space-between;
}
</style>
新写法
<style lang="scss">
.cart {
width: 600px;
margin: 0 auto;
.cart-header {
.form-head {
display: flex;
justify-content: space-between;
}
}
.cart-footer {
display: flex;
justify-content: space-between;
}
}
</style>
============================================================================
- 2)运算(Operations),导入(Importing) 与 less 基本相同
============================================================================
- 3)变量(Variables)
<style lang="scss">
$width:600px;
.cart {
width: $width;
margin: 0 auto;
.cart-header {
.form-head {
display: flex;
justify-content: space-between;
}
}
.cart-footer {
display: flex;
justify-content: space-between;
}
}
</style>
编译结果是;
.cart {
width: 600px;
margin: 0 auto;
.cart-header {
.form-head {
display: flex;
justify-content: space-between;
}
}
.cart-footer {
display: flex;
justify-content: space-between;
}
}
============================================================================
- 4)混合(Mixins)
- 混合器使用
@mixin标识符定义 - 通过
@include来使用这个混合器
// 定义
@mixin df {
display: flex;
}
.cart {
width: $width;
margin: 0 auto;
.cart-header {
.form-head {
@include df; // 定义 使用
justify-content: space-between;
}
}
.cart-footer {
@include df;
justify-content: space-between;
}
}
3、实现简单购物车的制作
- 基础结构

父组件
<template>
<div class="cart">
<div class="cart-header">
<h3>全部商品</h3>
<div class="form-head">
<div>
<input type="checkbox" name="" id="all" />
<label for="all">全选</label>
</div>
<span>商品</span>
<span>单价</span>
<span>数量</span>
<span>小计</span>
<span>操作</span>
</div>
</div>
<CartItem />
<div class="cart-footer">
<div>
<input type="checkbox" name="" id="all1" />
<label for="all1">全选</label>
</div>
<span>删除选中的商品</span>
<span>已选商品 200 件</span>
<span>总价</span>
</div>
</div>
</template>
<script>
import CartItem from "./CartItem.vue";
export default {
components: { CartItem },
};
</script>
<style lang="scss">
$width:600px;
@mixin df {
display: flex;
}
.cart {
width: $width;
margin: 0 auto;
.cart-header {
.form-head {
@include df;
justify-content: space-between;
}
}
.cart-footer {
@include df;
justify-content: space-between;
}
}
</style>
子组件
<template>
<div class="cart-item">
<input type="checkbox" name="" id="">
<img src="https://img30.360buyimg.com/n0/s80x80_jfs/t1/132022/23/12216/60913/5f86195bEacd08599/c5dc348d3f943324.jpg.dpg" alt="">
<span>标题</span>
<span>$100</span>
<div class="count">
<button>-</button>
<input type="text">
<button>+</button>
</div>
<span>$100</span>
<button class="del">删除</button>
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang='less'>
@import '../assets/style.less';
@color:red;
/* 样式的处理 */
/* 1.直接在 style 内添加 scoped 将组件样式变成私有化 */
/* scoprd 作用是给所在组件内的的标签 添加一个相同,但又与其他组件不同的属性 data-v-xxxxx */
/* 所有样式都会使用这个属性选择器来书写 */
/* css 预处理 css 控制语言 高级的 css 语法
因为:浏览器不支持高级的 css 语法解决方法安装相应的工具包
- 1)less
- 步骤一:首先需要安装对应的包 `npm i less less-loader -D` */
// 语法
// a. 嵌套
// b. 运算
// c. 变量
.border-top-bottom {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.cart-item{
display: flex;
justify-content: space-between;
padding: 20px 0;
align-items: flex-start;
.border-top-bottom();
.count {
input {
width: @width + 10px;
// width: 30px 10 px;
}
}
.del {
color: @color;
&:hover{
color: aqua;
}
}
}
</style>
3.1 功能的实现与应用
- 1)创建空数组并且发送请求拿数据
<script>
import CartItem from "./CartItem.vue";
export default {
data(){
return {
carts: [] //创建空数组
}
},
components: { CartItem },
async mounted(){
this.carts = await this.$http.get('/cart'), //发送请求拿数据
}
};
</script>

- 2)使用 v-for循环展示获取到的内容
<CartItem v-for="item in carts" :key="item.id"/>
注意:当子组件需要父组件对象内的所有数据来展示的时候一个一个的传递太麻烦了 我们可以使用
- 1.直接将对象传递过去,需要什么内容直接用
info.xxx提取数据
父组件:
<CartItem v-for="item in carts" :key="item.id" :info="item" />
子组件:
<template>
<div class="cart-item">
<input type="checkbox" name="" id="" :checked="info.checked">
<img :src="info.imgSrc" alt="">
<span>{{info.title}}</span>
<span>${{info.price}}</span>
<div class="count">
<button>-</button>
<input type="text" :value="info.count">
<button>+</button>
</div>
<span>${{info.price * info.count}}</span>
<button class="del">删除</button>
</div>
</template>
<script>
export default {
props: ['info'] // 接收传递过来的 info
}
</script>
- 2.将对象的属性全部传递过去 可以利用 v-bind 简化程度
父组件
<CartItem v-for="item in carts" :key="item.id" v-bind="item" />
子组件
<template>
<div class="cart-item">
<input type="checkbox" name="" id="" :checked="checked">
<img :src="imgSrc" alt="">
<span>{{title}}</span>
<span>${{price}}</span>
<div class="count">
<button>-</button>
<input type="text" :value="count">
<button>+</button>
</div>
<span>${{price * count}}</span>
<button class="del">删除</button>
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count']
}
</script>
在上代码中如果文字过多,会显得太难看,这时候我们可以使用多行文本溢出省略号
<template>
<div class="cart-item">
......
// 给文字地方添加css 元素
<span class="title">{{title}}</span>
......
</template>
......
<style scoped lang='less'>
......
.cart-item{
......
.title {
width: 80px;
// 老版弹性盒子
display: -webkit-box;
// 元素 垂直排列
-webkit-box-orient: vertical;
// 控制显示的行数
-webkit-line-clamp: 3;
// 溢出隐藏
overflow: hidden;
text-overflow: clip;
}
......
</style>
完成什么代码后得到的样式展示为

3.2 利用请求方式实现购物车功能
- 1)实现删除功能
父组件中定义 删除方法
使用:delete进行操作
- 先删除数据库内的,数据库内的删除成功了 ,然后在修改本地的
<script>
。。。。。
methods:{
// 删除操作
async del(id){
// 先删除数据库内的,数据库内的删除成功了 ,然后在修改本地的
await this.$http.delete('/cart/' + id)
}
}
};
</script>
将删除方法传递到 子组件中
<template>
<div>
<CartItem v-for="item in carts" :key="item.id" v-bind="item" @del="del" />
</div>
</template>
子组件接收传递过来的功能
<template>
<div class="cart-item">
.......
<button @click="del" class="del">删除</button>
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count'],
methods:{
del(){
this.$emit('del',this.id)
}
}
}
</script>
完成以上步骤 后端的数据以及删除成功,但前端页面并没有删除
如何删除前端页面的:在父组件中定义方法
<script>
。。。。。
methods:{
// 删除操作
async del(id){
// 先删除数据库内的,数据库内的删除成功了 ,然后在修改本地的
await this.$http.delete('/cart/' + id)
// 删除前端页面显示的
this.carts = this.carts.filter(item => item.id !== id)
}
}
};
</script>

- 2)对数量实现加减操作
父组件中定义 加减 功能
使用 patch 方法
<script>
。。。。
methods:{
。。。。
// 数量的添加
async add(id){
// 获取原来的数据是对象
const currentCartItem = this.carts.find(item => item.id === id )
//定义方法
await this.$http.patch(`/cart/${id}`,{count: currentCartItem.count + 1 } )
currentCartItem.count++
}
}
};
</script>
将添加方法传递到 子组件中
<template>
<div>
<CartItem v-for="item in carts" :key="item.id" v-bind="item" @del="del" @add="add" /> </div>
</template>
子组件接收传递过来的功能
<template>
<div class="cart-item">
.......
<button @click="add">+</button>
</div>
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count'],
methods:{
.......
add(){
this.$emit('add',this.id)
}
}
}
</script>

错误产生原因:当出现小数点的时候,数据运算会产生错误。
解决方法一:定义一个同一的函数,使用toFixed去解决,保留两位小数
<template>
....
<span>${{formatNum(price * count)}}</span>
.....
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count'],
methods:{
.....
formatNum(num){
return num.toFixed(2)//保留两位小数
}
}
}
</script>

解决方法二:使用过滤器来解决
<template>
。。。
<!-- 过滤器的用法 -->
<!-- {{ 参数1 | 过滤器(参数2,3,4)}} -->
<span>${{ (price * count) | formatNum}}</span>
</div>
</template>
<script>
export default {
。。。。
filters: {
formatNum(num) {
return num.toFixed(2);
},
}
}
</script>
如果过滤器想要如何地方都可以使用我们可以设置成全局过滤器
数量的减
<script>
。。。。
methods:{
。。。。
// 数量的减
async sub(id){
// 获取原来的数据是对象
const currentCartItem = this.carts.find(item => item.id === id )
//定义方法
await this.$http.patch(`/cart/${id}`,{count: currentCartItem.count - 1 } )
currentCartItem.count--
}
}
};
</script>
将添加方法传递到 子组件中
<template>
<div>
<CartItem 。。。 。@sub="sub"/> </div>
</template>
子组件接收传递过来的功能
当 数量为 1 我们应该禁止 减号使用::disabled="count === 1
<template>
<div class="cart-item">
.......
<button @click="sub" :disabled="count === 1>-</button>
</div>
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count'],
methods:{
.......
sub(){
this.$emit('sub',this.id)
}
}
}
</script>

- 3)复选框的选中与不选中
父组件中定义 选择也不选择的修改 功能
使用 patch 方法
<script>
。。。。
methods:{
。。。。
/ // 复选框的选中与不选中
async changeCheckedStatus(id){
// 获取原来的数据是对象
const currentCartItem = this.carts.find(item => item.id === id )
//定义方法
await this.$http.patch(`/cart/${id}`,{checked: !currentCartItem.checked } )
currentCartItem.checked = !currentCartItem.checked
},
}
};
</script>
将添加方法传递到 子组件中
<template>
<div
<CartItem
。。。。。。
@changeCheckedStatus="changeCheckedStatus"
/> </div>
</template>
子组件接收传递过来的功能
<template>
<div class="cart-item">
<input type="checkbox" .... @change="$emit('changeCheckedStatus',id)">
</div>
</template>
</script>
当进行加与减的操作的时候都是要点击这个商品,从侧面反映了我们选中了他
这时需要在 加减的接收处进行一个判断
<script>
。。。。
add(){
this.$emit('add',this.id);
// 当进行加与减的操作的时候都是要点击这个商品,从侧面反映了我们选中了他
if(!this.checked){
this.$emit('changeCheckedStatus', this.id)
}
},
sub(){
this.$emit('sub',this.id);
if(!this.checked){
this.$emit('c hangeCheckedStatus', this.id)
}
</script>
- 4)以下功能

- 使用计算属性
computed- res.count 老的
- item.count 新的
。。。。。。
<span>已选商品 {{totalInfo.count}}件</span>
<span>总价$ {{totalInfo.total | formatNum}}</span>
。。。。。。
<script>
export default {
。。。。
computed: {
// 商品个数
productNum(){
return this.cart.length
},
// 商品件数和总价 {count:30 , total: 500}
totalInfo(){
return this.carts.reduce(
(res, item) => ({
count: res.count + item.count,
total: res.total + item.price * item.count,
}),
{ count:0, total: 0 }
)
</script>

- 删除已选中的商品
绑定 @click 方法
<template>
。。。。。
<input type="checkbox" name="" id="all" v-model="isAllChecked" />
<label for="all">全选</label>
。。。。。
<input type="checkbox" name="" id="all1" v-model="isAllChecked" />
<label for="all1">全选</label>
</div>
<span @click="delAllChecked">删除选中的商品</span>
。。。。。。。
</template>
<script>
。。。。。。。
async delAllChecked (){
const res = this.filter((item) => item.checked) // 先拿到已选择的数据
await Promise.all(res.map(item => this.$http.delete('/cart/'+ item.id)))
// res.map(item => this.$http.delete('/cart/'+ item.id))
// 会解析成 [res.map(item => this.$http.delete('/cart/'+ item.id),
// res.map(item => this.$http.delete('/cart/'+ item.id))]数组的形式
this.carts = this.carts.filter((item) => !item.checked)// 得到新的
}
},
};
</script>
4、代码
- CartDemo.vue
<template>
<div class="cart">
<div class="cart-header">
<h3>全部商品{{productNum}}</h3>
<div class="form-head">
<div>
<input type="checkbox" name="" id="all" v-model="isAllChecked" />
<label for="all">全选</label>
</div>
<span>商品</span>
<span>单价</span>
<span>数量</span>
<span>小计</span>
<span>操作</span>
</div>
</div>
<CartItem
v-for="item in carts"
:key="item.id"
v-bind="item"
@del="del"
@add="add"
@sub="sub"
@changeCheckedStatus="changeCheckedStatus"
/>
<div class="cart-footer">
<div>
<input type="checkbox" name="" id="all1" v-model="isAllChecked" />
<label for="all1">全选</label>
</div>
<button @click="delAllChecked">删除选中的商品</button >
<span>已选商品 {{totalInfo.count}}件</span>
<span>总价$ {{totalInfo.total | formatNum}}</span>
</div>
</div>
</template>
<script>
import CartItem from "./CartItem.vue";
export default {
data() {
return {
carts: [], //创建空数组
};
},
components: { CartItem },
computed: {
// 商品个数
productNum(){
return this.carts.length
},
// 商品件数和总价 {count:30 , total: 500}
totalInfo(){
return this.carts.reduce(
(res, item) => ({
count: res.count + item.count,
total: res.total + item.price * item.count,
}),
{ count:0, total: 0 }
)
},
isAllChecked:{
get(){
return this.carts.every(item => item.checked)
},
set(val){
this.carts.forEach(item => {
item.checked = val
});
}
}
},
async mounted() {
this.carts = await this.$http.get("/cart"); //发送请求拿数据
},
methods: {
// 删除操作
async del(id) {
// 先删除数据库内的,数据库内的删除成功了 ,然后在修改本地的
await this.$http.delete("/cart/" + id);
// 删除前端页面显示的
this.carts = this.carts.filter((item) => item.id !== id);
},
// 数量的添加
async add(id) {
// 获取原来的数据是对象
const currentCartItem = this.carts.find((item) => item.id === id);
//定义方法
await this.$http.patch(`/cart/${id}`, {
count: currentCartItem.count + 1,
});
currentCartItem.count++;
console.log(0.1 + 0.2 === 0.3);
},
// 数量的添减
async sub(id) {
// 获取原来的数据是对象
const currentCartItem = this.carts.find((item) => item.id === id);
//定义方法
await this.$http.patch(`/cart/${id}`, {
count: currentCartItem.count - 1,
});
currentCartItem.count--;
},
// 复选框的选中与不选中
async changeCheckedStatus(id) {
// 获取原来的数据是对象
const currentCartItem = this.carts.find((item) => item.id === id);
//定义方法
await this.$http.patch(`/cart/${id}`, {
checked: !currentCartItem.checked,
});
currentCartItem.checked = !currentCartItem.checked;
},
async delAllChecked (){
const res = this.filter((item) => item.checked) // 先拿到已选择的数据
await Promise.all(res.map(item => this.$http.delete('/cart/'+ item.id)))
// res.map(item => this.$http.delete('/cart/'+ item.id))
// 会解析成 [res.map(item => this.$http.delete('/cart/'+ item.id),res.map(item => this.$http.delete('/cart/'+ item.id))]数组的形式
this.carts = this.carts.filter((item) => !item.checked)// 得到新的
}
},
};
</script>
<style lang="scss">
$width: 600px;
@mixin df {
display: flex;
}
.cart {
width: $width;
margin: 0 auto;
.cart-header {
.form-head {
@include df;
justify-content: space-between;
}
}
.cart-footer {
@include df;
justify-content: space-between;
}
}
</style>
- CartItem.vue
<template>
<div class="cart-item">
<input type="checkbox" name="" id="" :checked="checked" @change="$emit('changeCheckedStatus',id)">
<img :src="imgSrc" alt="">
<span class="title">{{title}}</span>
<span>${{price}}</span>
<div class="count">
<button @click="sub" :disabled="count === 1 ">-</button>
<input type="text" :value="count">
<button @click="add">+</button>
</div>
<!-- 过滤器的用法 -->
<!-- {{ 参数1 | 过滤器(参数2,3,4)}} -->
<span>${{ (price * count) | formatNum}}</span>
<button @click="del" class="del">删除</button>
</div>
</template>
<script>
export default {
props: ['id','imgSrc','title','price','checked','count'],
methods:{
del(){
this.$emit('del',this.id)
},
add(){
this.$emit('add',this.id);
// 当进行加与减的操作的时候都是要点击这个商品,从侧面反映了我们选中了他
if(!this.checked){
this.$emit('changeCheckedStatus', this.id)
}
},
sub(){
this.$emit('sub',this.id);
if(!this.checked){
this.$emit('c hangeCheckedStatus', this.id)
}
}
}
// 过滤器
// filters: {
// formatNum(num) {
// return num.toFixed(2);
// },
// }
}
</script>
<style scoped lang='less'>
@import '../assets/style.less';
@color:red;
/* 样式的处理 */
/* 1.直接在 style 内添加 scoped 将组件样式变成私有化 */
/* scoprd 作用是给所在组件内的的标签 添加一个相同,但又与其他组件不同的属性 data-v-xxxxx */
/* 所有样式都会使用这个属性选择器来书写 */
/* css 预处理 css 控制语言 高级的 css 语法
因为:浏览器不支持高级的 css 语法解决方法安装相应的工具包
- 1)less
- 步骤一:首先需要安装对应的包 `npm i less less-loader -D` */
// 语法
// a. 嵌套
// b. 运算
// c. 变量
.border-top-bottom {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.cart-item{
display: flex;
justify-content: space-between;
padding: 20px 0;
align-items: flex-start;
.border-top-bottom();
.title {
width: 80px;
// 老版弹性盒子
display: -webkit-box;
// 元素 垂直排列
-webkit-box-orient: vertical;
// 控制显示的行数
-webkit-line-clamp: 3;
// 溢出隐藏
overflow: hidden;
text-overflow: clip;
}
.count {
input {
width: @width + 10px;
// width: 30px 10 px;
}
}
.del {
color: @color;
&:hover{
color: aqua;
}
}
}
</style>
- App.vue
<template>
<div>
<CartDemo />
</div>
</template>
<script>
import CartDemo from './components/CartDemo.vue';
export default {
components: { CartDemo },
async created() {
const res = await this.$http.get('/cart');
console.log(res);
}
}
</script>
<style>
</style>
- http.js
// axios 封装
import axios from 'axios'
import Vue from 'vue'
const instance = axios.create({
// 请求基地址
baseURL: "http://localhost:3008/",
timeout: 2000 // 控制时间 2000 = 2s,
// 请求头的配置
// headers
})
// 请求拦截器
// 例:提示开会员
instance.interceptors.request.use((config) => {
// 请求头配置 config
// config.auth = 'token'
return config
})
// 响应拦截器
instance.interceptors.response.use((res) => {
return res.data
})
// vue 全局加上 $http
// 在组件中使用 this.$http 就相当于 instance 了
Vue.prototype.$http = instance
- main.js
import Vue from 'vue'
import App from './App.vue'
import './plugins/http'
import './plugins/utils'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
- data.json
{
"cart": [
{
"id": "ygy6y7",
"imgSrc": "https://img30.360buyimg.com/n0/s80x80_jfs/t1/132022/23/12216/60913/5f86195bEacd08599/c5dc348d3f943324.jpg.dpg",
"title": "Apple iPhone 12 (A2404) 128GB 白色 支持移动联通",
"price": 4899,
"checked": false,
"count": 1
},
{
"id": "ygyte7",
"imgSrc": "https://img20.360buyimg.com/n0/s80x80_jfs/t1/222320/23/22353/38203/6384d1a1Eebf9b463/9deecbd336d2a17a.jpg.dpg",
"title": "Apple iPhone 13 (A2634) 256GB 粉色 支持移动联通电信5G 双卡双待手机",
"price": 6090,
"checked": true,
"count": 1
}
,
{
"id": "yqdrg7",
"imgSrc": "https://img30.360buyimg.com/n0/s80x80_jfs/t1/179091/36/28087/35197/632873cbE8079c6b0/d6f86f1b1d5f112d.jpg.dpg",
"title": "荣耀70 IMX800三主摄 双曲屏设计 高通骁龙778G Plus 66W快充 5G手机 8GB+256GB 墨玉青",
"price": 2399,
"checked": true,
"count": 1
}
]
}
5、总结
过滤器
什么时间可以考虑到过滤器
- 数字的格式化 (保留两位小数)
- 日期的格式化
- 字符串的格式化
自定义指令
自定义指令我们可以写成局部与全局
- 局部
<template>
<div>
<CartDemo />
<!-- 让输入框出现的时候就获得交点 -->
<!-- 有些对真实 dom 的操作 可以通过自定义指令来实现 -->
<input v-focus type="text">
</div>
</template>
<script>
import CartDemo from './components/CartDemo.vue';
export default {
components: { CartDemo },
async created() {
const res = await this.$http.get('/cart');
console.log(res);
},
directives: {
focus: {
// 当被绑定的元素插入到 DOM 中时 使用
inserted(el){
el.focus()
}
}
}
}
</script>
<style>
</style>
- 全局 需要写在:main.Js 但需要写在 new Vue之前
- 定义好了后,在需要使用的定义直接
v-focus就可以使用
import Vue from 'vue'
import App from './App.vue'
import './plugins/http'
import './plugins/utils'
Vue.config.productionTip = false
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时 使用
inserted: function (el){
// 聚交元素
el.focus()
}
})
new Vue({
render: h => h(App),
}).$mount('#app')
-还可以写成 v-focus:a.b = 'c'
- a 指令参数
- b 指令修饰符可以写多个
- c 指令的值
- 对于 v-focus:a.b = ‘c’`传递过来的我们接收方式可以用
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
注意对于
inserted使用地方是上来就需要进行操作的,比如判断用户是否注册,弹窗的广告等等
<input v-focus:x.a.b="false" type="text">
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时 使用
inserted: function (el,{value,arg,modifiers}){
// 聚交元素
console.log(value)
console.log(arg)
console.log(modifiers)
el.focus()
}
})

本文介绍了在Vue项目中如何进行组件封装,详细探讨了less和sass的安装、使用,包括嵌套、运算、变量、混合和导入等高级特性。接着,通过实现一个简单的购物车功能,讲解了如何处理样式、数据操作、事件传递,包括商品的增删、数量调整及选中状态。最后,提到了过滤器和自定义指令的使用场景和定义方式。

177

被折叠的 条评论
为什么被折叠?



