Vue-cli
vue-cli是vue官方提供的脚手架工具 command line interface
- 通过
@vue/cli
实现的交互式的项目脚手架。
安装
npm install -g @vue/cli
# OR
yarn global add @vue/cli
查看版本
vue --version
升级
npm update -g @vue/cli
# 或者
yarn global upgrade --latest @vue/cli
创建一个项目
vue create my-project
# OR
vue ui
代码的意义
main.js
// 关闭生产提示
Vue.config.productionTip = false;
// 在new Vue之前做全局操作
Vue.component("Child", Child);
new Vue({
render: h => h(App)
// createElement具备模板能力
// render: createElement => createElement(App)
}).$mount("#app");
/*
import Vue from "vue"; --> vun.runtime.esm.js
1. vun.runtime.esm.js 只包含运行时版本(不具备编译模板能力)
优点:
1. 使用简单
2. 体积小
import Vue from "vue/dist/vue.esm.js";
2. vun.esm.js 完整版本(具备编译模板能力)
- 引入组件
- 注册组件
- 页面中使用组件
问题:
1. 太麻烦了
2. 文件体积更大
*/
其他代码
<!-- 通过标签属性的方式(props方式),给子组件传递数据 -->
<Father :num="num" />
export default {
name: "Father", // 组件名称
// 声明接受props数据的类型
// 一定要声明接受数据,否则数据不能通过this直接访问
// props: ["num"], // 代表要接受的数据是num
// props: {
// num: Number // 代表要接受的数据是num且类型是number
// },
props: {
num: {
// 代表要接受的数据是num、类型是number、必须传
type: Number,
required: true,
},
},
data() {
return {};
},
/*
data有两种写法:1. 对象 2. 函数
在普通页面中,两种写法都想
但是在组件中,必须使用函数
如果在组件中,data使用对象,复用组件时这多个组件会共享同一份data数据
如果在组件中,data使用函数,复用组件时这多个组件会调用函数得到一份新data数据,
每个组件的data数据都会不一样,所以不会互相影响
*/
};
组件间通信
组件间通信基本原则
(1) 不要在子组件中直接修改父组件的状态数据
(2) 数据在哪, 更新数据的行为(函数)就应该定义在哪
Vue组件间通信方式
(1) props
(2) vue的自定义事件
(3) 全局事件总线
(4) 消息订阅与发布
(5) slot
(6) vuex(后面单独讲)
1.props
单项数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。
传递
<!-- 通过标签属性的方式(props方式),给子组件传递数据 -->
<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<Father :num="num" />
子组件接收
// 声明接受props数据的类型
// 一定要声明接受数据,否则数据不能通过this直接访问
// props: ["num"], // 代表要接受的数据是num
// props: {
// num: Number // 代表要接受的数据是num且类型是number
// },
props: {
num: {
// 代表要接受的数据是num、类型是number、必须传
type: Number,
required: true,
},
},
小结
(1) 此方式用于父组件与子组件之间传递数据
(2) 所有标签属性都会成为组件对象的属性, 模板页面可以直接引用
(3) 问题:
a. 如果需要向非子后代传递数据必须多层逐层传递
b. 兄弟组件间也不能直接props通信, 必须借助父组件才可以
2.Vue自定义事件
/*
自定义事件
作用:用来子组件向父组件通信
注意: 给哪个组件绑定自定义事件,就只有那个组件可以触发(使用)
使用:
1. 方式一
绑定自定义事件
<Child @add="add" />
触发事件
this.$listeners.add();
2. 方式二
绑定自定义事件
<Child ref="child" />
mounted() {
this.$refs.child.$on('add', this.add)
}
触发事件
this.$emit('add')
所有组件实例对象都具备以下方法:
$on(eventName, listener) 绑定自定义事件(持久)
$once(eventName, listener) 绑定自定义事件(一次性)
$off(eventName, listener) 解绑事件
$emit(eventName, data) 触发自定义事件
*/
绑定事件
mounted() {
// 绑定自定义事件 在挂载成功生命周期钩子函数
this.$refs.child.$on("add", this.add);
}
触发事件
methods: {
handleClick() {
/*
this._events 存储事件的容器
获取到自定义事件回调函数
this.$listeners.eventName
*/
// this.$listeners.add();
// 触发自定义事件 1,2,3表示传参
this.$emit("add", 1,2,3)
}
3.全局事件总线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WrZHEK3k-1606142042711)(F:\前端基础课堂笔记\Vue\Vue文档\全局事件总线.png)]
(1) 所有组件对象的原型对象的原型对象就是Vue的原型对象
a. 所有组件对象都能看到Vue原型对象上的属性和方法
Vue.prototype.bus = new Vue(), 所有的组件对象都能看到$bus这个属性对象
(2) 全局事件总线
a. 包含事件处理相关方法的对象(只有一个)
b. 所有的组件都可以得到
绑定事件两种方法
// 给Vue原型对象上添加一个可以绑定事件的对象
// 可以绑定事件的对象:vm 和 组件实例对象
//Vue.prototype.$bus = new Vue();
new Vue({
beforeCreate() {
Vue.prototype.$bus = this;
},
render: h => h(App),
}).$mount('#app')
绑定事件
mounted() {
// 绑定事件 接收数据
this.$bus.$on("add", () => {
this.num += 1;
});
}
触发事件
methods:{
add() {
//触发事件 传递数据
this.$bus.$emit("add");
}
}
4.slot-插槽
此方式用于父组件向子组件传递带数据的标签
1.默认插槽:
<!--父组件 -->
<AChild>
<p>A的slot</p>
</AChild>
<!--子组件 -->
<div>
<h2>AAA</h2>
<!-- 使用父组件以插槽方式传递的标签数据 -->
<slot></slot>
</div>
2.具名、命名插槽: 给每一个插槽取一个名字
<!--父组件 -->
<BChild>
<!-- 旧语法:slot="名称" -->
<template slot="header">
<p>B的具名slot1:header {{msg}}</p>
</template>
<!-- 新语法:v-slot:名称 -->
<template v-slot:content>
<p>B的具名slot2:content</p>
</template>
<!-- 新语法可以简写:#名称 -->
<template #footer>
<p>B的具名slot:footer</p>
</template>
</BChild>
<!--子组件 -->
<div>
<h1>BBB</h1>
<!-- 通过name属性来决定使用哪个具名插槽 -->
<slot name="header"></slot>
<p>------------</p>
<slot name="content"></slot>
<p>------------</p>
<slot name="footer"></slot>
</div>
3.作用域插槽
父组件插槽可以接受子组件通过slot传递的props数据
<!--父组件 -->
<CChild>
<!-- 父组件插槽可以接受子组件通过slot传递的props数据 -->
<!-- { person } -> 就是对数据进行解构赋值 -->
<!-- <template #list="{ person }"> -->
<template #list="{person:{name, age}}">
<ul>
<li>姓名:{{name}}</li>
<li>年龄:{{age}}</li>
</ul>
</template>
</CChild>
<slot name="list" :person="person"></slot>
data() {
return {
person: {
name: "suzy",
age: 25
}
};
}
vue的axios使用
在挂载成功钩子函数中发送请求
mounted() {
// 将loading改为true:代表请求中
this.isLoading = true;
axios
.get("http://localhost:3000/star")
.then(res => {
// 代表请求完成
this.isLoading = false;
//console.log(res)
const { name, url } = res.data.login[0];
this.repo.url = url;
this.repo.name = name;
})
.catch(err => {
// 代表请求完成
this.isLoading = false;
console.log(err);
alert("网络错误,请刷新试试");
});
}