昨日回顾
组件-一个单vue文件就是一个组件-是一个独立的个体-数据独立-data返回的是一个新对象
html + css + js- template-html script- js style-css-(scoped)- 加scoped会给所有的标签加上一个唯一的hash值- 样式只对当前组件生效
既然组件相互独立,组件的通讯。父组件给子组件传值 子组件给父祖件传值 非父子关系传值
- 父 => 子传值-确定父子关系- 被引入的组件-子组件
父 => 子 props
<template> <div> 给谁传就在谁的标签上写属性 <child :name="name" /> </div> </template> <script> import Child from './Child', export default { name: 'parent', data() { return { name: '章三' } }, props: ["username"], computed: { firstName() { return this.name.substr(0, 3) } }, // 局部注册-只能在当前注册的组件使用 components: { Child } } </script>
子组件
<template> <div>{{ name }}</div> </template> <script> export default { name: 'child', props: { name: { // 这里是对name的要求 type: String, required: true, // 必须传这个属性 default: "李四" // 这个值会在没有传name属性时生效 } } // props: ["name"] // 数组-对象 } </script>
要有父子关系,要有子组件的标签,给谁传就在谁的标签上写属性, 子组件要接收属性
子组件 - 父组件传值- 三种用法
官方-自定义事件
子组件触发事件
<template> <div>{{ name }}</div> <button @click="updateName">改变父组件的名字</button> </template> <script> export default { name: 'child', props: { name: { // 这里是对name的要求 type: String, required: true, // 必须传这个属性 default: "李四" // 这个值会在没有传name属性时生效 } }, methods: { updateName () { // 触发自定义事件 this.$emit("updateName", "王武") //this.name = "" // 这种方法是错误的 单向数据流 } } // props: ["name"] // 数组-对象 } </script>
父组件监听事件
<template> <div> 给谁传就在谁的标签上写属性 <child :name="name" @updateName="updateName" /> </div> </template> <script> import Child from. './Child', export default { name: 'parent', data() { return { name: '章三' } }, props: ["username"], computed: { firstName() { return this.name.substr(0, 3) } }, // 局部注册-只能在当前注册的组件使用 components: { Child }, methods: { updateName (name) { this.name = name // 修改值 } } } </script>
子组件要触发事件, 父组件要监听事件
$emit(“自定义事件名称”, 参数)
v-on:自定义事件名=”方法”
- 非关系型组件传值
eventBus- 事件总线- 将触发事件和监听事件都放在了一个实例上
- 新建事件总线的一个实例 ```javascript import Vue from ‘vue’
export default new Vue() // 事件总线
- 触发事件
```javascript
import eventBus from ''
methods: {
test() {
eventBus.$emit("abc", 123)
}
}
- 监听事件-要越早越好-组件一创建就监听 ```javascript import eventBus from ‘’
export default { created() { eventBus.$on(“abc”, (value) => { // value就是123 }) }
}
TodoMVC的案例
```vue
<template>
<div :name="name" @updateName=""></div>
</template>
<script>
export default {
name: 'App',
components: {}, // 注册组件
data() {
return {}
},
filters: {
// 过滤器
},
computed: {
// 计算属性
},
watch: {
// 侦听器
},
methods: {
// 存储方法的
},
created() {
// 会在组件创建时触发
}
}
</script>
真正的应用 都是综合的结合
1. 组件的生命周期
vue的组件生命周期-从创建到销毁的整个过程
v-if 会创建并删除元素
一个组件的标签就是一个组件的实例
-
2.组件的生命周期的钩子函数
初始化阶段- beforeCreate - 创建实例过程 - created
- 挂载阶段- beforeMount - 挂载过程 - mounted (挂载完成-已经有dom了)
- 更新阶段 - beforeUpdate - 更新过程 - updated (数据驱动视图)
- 销毁阶段 - beforeDestroy - 销毁过程 - destroyed(一般都在beforeDestroy)
3. 初始化阶段的过程
初始化阶段- beforeCreate - 创建实例过程 - created
鸡肋-beforeCreate- data和methods不能用-几乎不用
created才可以用data和methods方法
created-CRUD- 增删改查- 查询-created-data和methods已经使用了
一般的查询网络请求放在created
4. 挂载阶段
- 挂载阶段- 模版编译-虚拟dom-真实dom- 挂载到页面
- 挂载阶段- beforeMount - 挂载过程 - mounted (挂载完成-已经有dom了)
beforeMount 鸡肋事件,几乎不用
mounted可以获取真实dom -echarts
echarts.init(dom) // 一般放在mounted中进行
5. 更新阶段
数据变化-就会触发钩子函数
export default {
data () {
return {
a:1,
b:2,
c:3,
d:4
...
}
},
beforeUpdate() {},
updated() {}
}
watch-侦听单个的变量
任意变量的触发-都会执行钩子函数
- 鸡肋函数
6.销毁阶段
beforeDestroy- 销毁所有的监视器和事件 destroyed
beforeDestroy- 销毁被全局引用的变量- 定时器
<template>
<div>
<h1>倒计时{{ count }}</h1>
</div>
</template>
<script>
export default {
name: "TimerCount",
data() {
return {
count: 60,
};
},
beforeCreate() {
console.log("beforeCreate");
},
created() {
console.log("created");
// 记录标记
this.flag = setInterval(() => {
this.count--;
}, 1000);
},
beforeMount() {
console.log("beforeMount");
},
mounted() {
console.log("mounted");
},
beforeUpdate() {
console.log("beforeUpdate");
},
updated() {
console.log("updated");
},
beforeDestroy() {
clearInterval(this.flag); // 清理定时器
console.log("beforeDestroy");
},
destroyed() {
console.log("destroyed");
},
};
</script>
<style>
</style>
created-获取数据
mounted- 获取dom
beforeDestroy- 销毁定时器相关的引用
7. axios的介绍
- 请求的库- (浏览器)客户端使用- nodejs也可以使用
- 支持Promise
- 主流的请求工具库-90%的项目react-vue都使用它
http://www.axios-js.com/ axios的官网地址
安装axios
$ npm i axios
用法 ```javascript axios({ method: ‘get/post/put/delete/patch’, // 类型 url: ‘’, // 请求的接口地址 data: {}, // 请求体参数 body参数 post/put/delete/patch params: {} // 参数- 地址参数-url参数- 拼接到url地址上 }).then(result => { // result就是返回结果
}).catch(error => { // 报错的信息
})
- get - 获取数据-没有请求体参数
- post- 提交数据
- put- 更新数据- 完整更新- { id: 1, name: '章三' }- 数据会完全覆盖
- patch- 增量更新- 部分更新- { id: 1, name: '章三' }-只更新name属性
- delete-删除
> 简写
axios.get("地址") // get请求<br />axios.post("地址") // post请求<br />axios.delete("地址") // delete请求<br />axios.patch("地址") // patch请求<br />axios.put("地址") // put请求
解析- axios().then().catch()
> axios返回的是一个Promise对象
- 三种状态-pending(等待) 成功 失败
```javascript
new Promise(function (resolve, reject) {
resolve() // 成功
// reject() // 失败
}).then(result => {}).catch(error=> {
})
axios的实现机制 ```javascript function axios () { return new Promise(function (resolve, reject) { XMLHttpRequest xml = new XMLHttpRequest() xml.open(“get”, “”) xml.send() xml.onload = function () { resolve(JSON.parse(xml.response))
} xml.onerror = function () { reject() }})
}
axios().then(result => {
})
<a name="ulKU9"></a>
## 8. axios获取数据
1.安装axios
```bash
$ npm i axios
- 在你需要的组件中引入axios
import axios from 'axios'
axios的返回结果数据中 默认包了一层data数据
<template>
<div id="app">
<ul>
<li v-for="item in channels" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
components: {},
data() {
return {
channels: [], // 频道列表
};
},
created() {
// this
this.getChannels();
},
methods: {
getChannels() {
axios({
// method: "get",
url: "http://toutiao.itheima.net/v1_0/channels",
}).then(({ data }) => {
// console.log(data.data.channels);
this.channels = data.data.channels;
});
},
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
ul li {
list-style: none;
width: 80px;
text-align: center;
}
ul {
display: flex;
flex-direction: row;
}
</style>
9. axios发送post请求
绘制页面结构 ```vue
短信登录
发送验证码
短信登录
短信登录
this.$refs.属性 - 父组件可以拿到子组件的this ## 13.使用ref实现父传子 1. 确定父子关系 1. 给子组件的标签一个ref属性 1. this.$refs.属性获取子组件的实例(this) 1. 通过实例就可以调用方法 传值 ```vue
<a name="wclnF"></a>
## 14. $nextTick方法
> 会等到数据渲染完成,dom更新之后执行
this.$nextTick(函数体)<br />Vue.nextTick(函数体)
```vue
export default {
methods: {
update() {
this.count++ // 更新数据
this.$nextTick(() => {
// 渲染更新完成之后,此时可以获取最新的数据
})
}
}
}
场景: 一般用在需要获取更新的dom的时候,又或者 props传值
props更新要重新渲染,也是一个异步过程
父组件 =》 子组件的方法
ref- 获取子组件的实例-this
- 子组件的属性有props属性-不能保证已经更新完了
- nextTick 执行的时候 说明渲染完成了 数据已经更新
当你遇到你获取的数据的是上一次的时候,说明你遇到了异步,就可以使用nextTick
15.json-server的使用
json 开启一个服务器
- json-server它是一个npm包,快速生成8个左右的接口,包含增删改查
安装json-server
$ npm i -g json-server
新建一个json文件
{ "goodsList": [ { "id": 1, "goods_name": "班俏BANQIAO超火ins潮卫衣女士2020秋季新款韩版宽松慵懒风薄款外套带帽上衣", "goods_img": "https://www.escook.cn/vuebase/pics/1.png", "goods_price": 108, "goods_count": 1, "goods_state": true }, { "id": 2, "goods_name": "嘉叶希连帽卫衣女春秋薄款2020新款宽松bf韩版字母印花中长款外套ins潮", "goods_img": "https://www.escook.cn/vuebase/pics/2.png", "goods_price": 129, "goods_count": 1, "goods_state": true }, { "id": 3, "goods_name": "思蜜怡2020休闲运动套装女春秋季新款时尚大码宽松长袖卫衣两件套", "goods_img": "https://www.escook.cn/vuebase/pics/3.png", "goods_price": 198, "goods_count": 1, "goods_state": false }, { "id": 4, "goods_name": "思蜜怡卫衣女加绒加厚2020秋冬装新款韩版宽松上衣连帽中长款外套", "goods_img": "https://www.escook.cn/vuebase/pics/4.png", "goods_price": 99, "goods_count": 1, "goods_state": false }, { "id": 5, "goods_name": "幂凝早秋季卫衣女春秋装韩版宽松中长款假两件上衣薄款ins盐系外套潮", "goods_img": "https://www.escook.cn/vuebase/pics/5.png", "goods_price": 156, "goods_count": 1, "goods_state": true }, { "id": 6, "goods_name": "ME&CITY女装冬季新款针织抽绳休闲连帽卫衣女", "goods_img": "https://www.escook.cn/vuebase/pics/6.png", "goods_price": 142.8, "goods_count": 1, "goods_state": true }, { "id": 7, "goods_name": "幂凝假两件女士卫衣秋冬女装2020年新款韩版宽松春秋季薄款ins潮外套", "goods_img": "https://www.escook.cn/vuebase/pics/7.png", "goods_price": 219, "goods_count": 2, "goods_state": true }, { "id": 8, "goods_name": "依魅人2020休闲运动衣套装女秋季新款秋季韩版宽松卫衣 时尚两件套", "goods_img": "https://www.escook.cn/vuebase/pics/8.png", "goods_price": 178, "goods_count": 1, "goods_state": true }, { "id": 9, "goods_name": "芷臻(zhizhen)加厚卫衣2020春秋季女长袖韩版宽松短款加绒春秋装连帽开衫外套冬", "goods_img": "https://www.escook.cn/vuebase/pics/9.png", "goods_price": 128, "goods_count": 1, "goods_state": false }, { "id": 10, "goods_name": "Semir森马卫衣女冬装2019新款可爱甜美大撞色小清新连帽薄绒女士套头衫", "goods_img": "https://www.escook.cn/vuebase/pics/10.png", "goods_price": 153, "goods_count": 1, "goods_state": false } ] }
启动服务
$ json-server ./db.json --watch
相当于后台服务,已经有接口了
16. 初始化项目-拆分组件
创建vue项目
$ vue create cart
安装bootstrap
$ npm i bootstrap
在main.js中引入bootstrap的样式
// 导入 bootstrap 样式文件: import 'bootstrap/dist/css/bootstrap.css';
启动服务
- 头部组件
CartHeader.vue
<template>
<div class="cart-header">购物车</div>
</template>
<script>
export default {};
</script>
<style>
.cart-header {
z-index: 999;
height: 45px;
line-height: 45px;
text-align: center;
background-color: #1d7bff;
color: #fff;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
</style>
- CartFooter.vue ```vue
<a name="KuBES"></a>
## 17.获取数据显示到购物车上
- json-server
- axios
1. 安装axios
```bash
$ npm i axios
- 配置axios的基础地址 main.js ```javascript axios.defaults.baseURL = “http://localhost:3000“
3. App.vue 获取商品数据
```vue
<template>
<div id="app">
<cart-header></cart-header>
<goods-item v-for="item in list" :key="item.id" :item="item"></goods-item>
<cart-footer></cart-footer>
</div>
</template>
<script>
import CartHeader from "./components/CartHeader.vue";
import CartFooter from "./components/CartFooter.vue";
import GoodsItem from "./components/GoodItem.vue";
import axios from "axios";
export default {
name: "App",
components: {
CartHeader,
CartFooter,
GoodsItem,
},
data() {
return {
list: [],
};
},
created() {
this.getGoodsList();
},
methods: {
getGoodsList() {
axios.get("/goodsList").then(({ data }) => {
this.list = data;
});
},
},
};
</script>
<style>
#app {
padding-top: 50px;
padding-bottom: 50px;
}
</style>
- GoodsItem中接收数据,并渲染
```vue
{{ item.goods_name }}¥ {{ item.goods_price }} {{ item.goods_count }}
```