要件:
ケースショー:
コード表示:
HTML部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div class="container">
<my-cart></my-cart>
</div>
</div>
<script src="./js/vue.js"></script>
<script>
//插入自己写的js
</script>
</body>
CSSのセクション:(将来的には、CSSスタイルを記述して、可能な限り階層的なセレクターを記述し、それらは重い関係を持っています)
<style>
.container {
width: 100%;
height: 100%;
}
.container .cart {
width: 300px;
margin: auto;
}
.container .title {
background-color: lightblue;
height: 40px;
line-height: 40px;
text-align: center;
}
.container .total {
background-color: #FFCE46;
height: 50px;
line-height: 50px;
text-align: right;
}
.container .total button {
margin: 0 10px;
background-color: #DC4c40;
height: 35px;
width: 80px;
border: 0;
}
.container .total span {
color: red;
font-weight: bold;
}
.container .item {
height: 55px;
line-height: 55px;
position: relative;
border-top: 1px solid #ADD8E6;
}
.container .item img {
width: 45px;
height: 45px;
margin: 5px;
}
.container .item .name {
position: absolute;
width: 90px;
top: 0px;
left: 55px;
font-size: 16px;
}
.container .item .change {
width: 100px;
position: absolute;
top: 0;
right: 50px
}
.container .item .change a {
font-size: 20px;
width: 30px;
text-decoration: none;
background-color: lightgray;
vertical-align: middle;
}
.container .item .change .num {
width: 40px;
height: 25px;
}
.container .item .del {
user-select: none;
/* 双击不选中 */
position: absolute;
top: 0px;
right: 0px;
width: 40px;
text-align: center;
font-size: 40px;
cursor: pointer;
color: red;
}
.container .item .del:hover {
background-color: orange;
}
</style>
JSの部品:(キー分析)
<script>
//局部定义的变量组件一定要放在 全局component前面!!!!
var CartTitle = {
props: ['uname'],
template: `
<div class="title">{{uname}}的购物车</div>
`
}
var CartList = {
props: ['lists'],
template: `
<div>
<div class="item" v-for="item in lists" :key="item.id">
<img :src="item.img"/>
<!-- 不能写成{{item.img}} 直接写item.img-->
<div class="name">{{item.name}}</div>
<div class="change">
<a href="" @click.prevent='sub(item.id)'> - </a>
<input name="" type="text" class="num" :value='item.num' @blur='changeNum(item.id,$event)'></input>
<a href="" @click.prevent='add(item.id)'>+ </a>
</div>
<div class="del" @click='del(item.id)'>×</div>
</div>
</div>
`,
methods: {
changeNum: function(id, event) {
this.$emit('change-num', {
id: id,
type: 'change',
num: event.target.value
})
},
//按+ -得到的数据也传递到changeNum
sub: function(id) {
this.$emit('change-num', {
id: id,
type: 'sub'
})
},
add: function(id) {
this.$emit('change-num', {
id: id,
type: 'add'
});
},
del: function(id) {
//把id传给父组件
this.$emit('cart-del', id);
}
},
}
//计算总价组件
var CartTotal = {
props: ['lists'],
template: `
<div class="total">
<span>总价:{{total}}</span>
<button>结算</button>
</div>
`,
computed: {
//利用计算属性来计算总价 要有return值
total: function() {
//计算商品总价
var sum = 0;
this.lists.forEach(item => {
//foeEach遍历出数据
sum += item.price * item.num;
//总价=单价x数量
})
return sum;
}
},
}
Vue.component('my-cart', {
data() {
return {
uname: 'XXW',
lists: [{
id: 1,
name: 'TCL彩电',
price: 1200,
num: 1,
img: 'img/a.jpg',
}, {
id: 2,
name: '机顶盒',
price: 800,
num: 1,
img: 'img/b.jpg',
}, {
id: 3,
name: '海尔冰箱',
price: 2200,
num: 1,
img: 'img/c.jpg',
}, {
id: 4,
name: '小米手机',
price: 1799,
num: 1,
img: 'img/d.jpg',
}, {
id: 5,
name: 'PPTV电视',
price: 1888,
num: 1,
img: 'img/e.jpg',
}, ]
}
},
template: `
<div class="cart">
<cart-title :uname="uname"></cart-title>
<cart-list :lists="lists" @change-num='changeNum($event)' @cart-del='delCart($event)'></cart-list>
<cart-total :lists="lists"></cart-total>
</div>
`,
components: {
//第一局部组件 定义太多全局组件容易起冲突
'cart-title': CartTitle,
'cart-list': CartList,
'cart-total': CartTotal
},
methods: {
changeNum: function(val) {
var reg = /^[0-9]{1,5}$/; //正则匹配不能输入中文
//分三种情况:输入域变更,加号变更,减号变更
if (val.type == 'change') {
if (reg.test(val.num)) {
console.log(reg.test(val.num)); //true
console.log(typeof val.num); //隐式迭代 变成string型
//根据子组件传递过来的数据,跟新list中对应的数据
this.lists.some(item => {
if (item.id == val.id) {
if (item.num > 0) {
//输入框不能为负值
item.num = val.num;
} else {
item.num = 0;
}
//终止遍历
return true;
}
});
} else {
console.log(reg.test(val.num)); //false
this.lists.some(item => {
if (item.id == val.id) {
item.num = 0;
//终止遍历
return true;
}
});
}
} else if (val.type == 'sub') {
//减一操作
this.lists.some(item => {
//不能减到0以下
if (item.id == val.id) {
if (item.num >= 1) {
item.num = item.num * 1 - 1;
//我的想法是给item.num*1 这样就又转number类型 直接把item.num 写成 item.Number(num)没有用 显示undefined
} else {
item.num = 0;
}
//终止遍历
return true;
}
});
} else if (val.type == 'add') {
//加一操作
this.lists.some(item => {
if (item.id == val.id) {
item.num = item.num * 1 + 1;
//终止遍历
return true;
}
})
}
},
delCart: function(id) {
this.lists = this.lists.filter(function(item) { //把筛选后的结果重新赋值给books
return item.id != id //返回那些id 不相等的对象 形成一个新的数组
})
}
},
});
var vm = new Vue({
el: '#app',
data: {}
})
</script>
jsコード分析:
1。ローカルに定義された変数コンポーネントは、グローバルコンポーネントの前に配置する必要があります。!!
2。<img :src="item.img"/>
{{item.img}}と書くことはできません!!item.imgに直接書き込む
3.computed
計算された属性を使用して戻り値を取得するreturn
4.正規表現マッチングを使用して、入力ボックスが数字のみを入力できるようにします。中国語では直接ゼロになります。
注意!!!:正規表現一致後の数データ型が変更されました(暗黙の反復)番号=>文字列、マイナス記号ボタンの追加につながるのは文字の追加です
ソリューション:
以下の加減算ボタンの増減のコードを以下のように変更
//加
item.num = item.num * 1 - 1;
//减
item.num = item.num * 1 + 1;
私の考えは、この方法でitem.num * 1を指定し、数値型を直接回してitem.numをitem.Number(num)として使用することはできず、結果は未定義であることです
5.(詳細処理)マイナスキーの操作では、<0にすることはできません。条件を使用して判断します。
6。削除ボタンを作成する2つの方法:
最初のもの:(分析は注を参照)
delCart: function(id) {
this.lists = this.lists.filter(function(item) { //把筛选后的结果重新赋值给books
return item.id != id //返回那些id 不相等的对象 形成一个新的数组
})
}
第2種(分析は注を参照)
delCart: function(id) {
// 根据id删除list中对应的数据
// 1、找到id所对应数据的索引
var index = this.list.findIndex(item => {
return item.id == id;
});
// 2、根据索引删除对应数据
this.list.splice(index, 1);
}