Fork me on GitHub

vue基础-下

组件

  • props

    组件的参数传递

  • slot

插槽在组件抽象设计中的应用

  • 自定义事件

父子组件的通信方式

组件的基础示例可以先看一波文档,但是我们一般都不会用这里的这种方式去定义我们的组件。(Vue.Component不会用)

我们直接从深入了解组件这个地方的文档开始吧。

通过父组件给子组件传递值,使用props来进行值的传递:

child.vue的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template lang="html">
<div class="com">
child components
{{ name }}
{{ age }}
</div>
</template>
<script>
// 子组件这边通过`props`这个属性就可以拿到父组件的值了
export default {
props: ["age"],
data() {
return {
name: "com"
};
}
};
</script>
<style>
</style>

父组件那边的代码为App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template lang="html">
<div id="app">
<!-- 这里传递的是动态的值,所以前面加上: -->
<child :age="age"/>
</div>
</template>
<script>
import child from "./components/child.vue";
import "./components/n";
export default {
name: 'app',
components: {
child
},
data(){
return{
age: 18
}
}
}
</script>
<style>
</style>

如果在子组件里面想去触发父组件里面的方法的话,可以使用$emit这个参数去进行。

大概过程是这样的:

child.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template lang="html">
<div class="com">
child components
{{ name }}
{{ age }}
<button type="button" name="button" @click="patch">发送到父组件</button>
</div>
</template>
<script>
export default {
props: ["age"],
data() {
return {
name: "com"
};
},
methods:{
patch: function(){
// 第一个是方法名,第二个是传递到父组件的参数
this.$emit('patch','wdlj');
}
}
};
</script>
<style>
</style>

父组件里面想要接收的话,这样即可App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<div id="app">
<p>{{ age }}</p>
<!-- age前面相当于加了一个动态的修饰符 -->
<child @patch="msg" :age="age">
</div>
<script>
import child from "./components/child"
export default {
name:"app",
components: {
child
},
data(){
return {
age: 18
}
},
methods:{
msg:function(b){
this.age += 1;
window.console.log(b);
}
}
}
</script>
</template>

如果是不同层级之间的组件去进行数据交互的话,那是需要去使用vuex的。

slot

我们在父组件里面引入一个子组件Child.vue,同时我们需要在子组件里面去动态添加一些东西,类似于下面的代码:

1
2
3
<child :age="age" @patch="msg">
<h1>我要加些内容在这里</h1>
</child>

但是显然按照上面的代码是铁定实现不了的。。。如果我们想动态地往组件里面加入东西,是需要一个叫做slot的API去加入一些东西的。

我们在子组件child的尾部加上<slot></slot>,这样上面的h1标签就可以动态地加入进去。如果有多个插槽的话,给插槽加里面加一个name属性即可。
子组件的插槽代码:

1
2
<slot name = "a"></slot>
<slot name = "b"></slot>s

父组件里面的代码为:

1
2
<h1 slot="a">我要加一些东西</a>
<h2 slot="b">我要加在下面哈哈哈哈</h2>

路由

路由的话,vue官网是有一个专门的文档可以供参考的,地址点击

安装一波vue-router

1
npm install vue-router

我们然后在src目录下面新建一个routes.js,里面的代码内容是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import Vue from "vue";
import VueRouter from "vue-router";
import pageA from "./pages/a.vue";
import pageB from "./pages/b.vue";
import App from "./App.vue";
Vue.use(VueRouter);
const routes = [
{ path: "/", component:App },
{ path: "/pagea", component: pageA },
{ path: "/pageb", component: pageB }
];
const router = new VueRouter({
routes
})
export default router;

大概这样写,pageApageB自己随便建立。

同时要引入使用这个路由的话,可以直接引入一波:

1
2
3
4
5
6
7
8
9
import Vue from 'vue'
import router from "./router";
Vue.config.productionTip = false
new Vue({
// render: h => h(App),
router
}).$mount('#app')

然后建立一个vue.config.js,里面可以添加一些webpack的配置项,我们可以这样写(和以前的webpack.config.js还是有异曲同工之妙的):

1
2
3
module.exports = {
runtimeCompiler: true
}

最后千万别忘了在index.html里面的挂载点里面加入一个router-view的模板。

1
2
3
4
5
6
<div id="app">
<router-view></router-view>
<router-link to ="/">首页</router-link>
<router-link to ="/pagea">PageA页面</router-link>
<router-link to ="/pageb">PageB页面</router-link>
</div>

这个router-link的作用和react-router-dom里面的Link是一样的哈哈哈哈。

Vuex

首先文档先献上:Vuex文档地址

建议多看看文档里面关于Vuex的讲解,其实我感觉这玩意儿比Redux要简化一点了,这里还是用一个计数器来作为例子(23333,redux也是用这个例子学的233)

直接来搞一波demo,先去src目录下新建一个store.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
// data,computed,props
const state = {
count: 1,
};
const mutations = {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
},
};
// 接收组件的用户行为,然后去修改一波state
const actions = {
increment: ({ commit }) => {
commit("increment");
},
decrement: ({ commit }) => {
commit("decrement");
},
};
export default new Vuex.Store({
state,
mutations,
actions,
});

store创建完成之后,去main.js里面直接搞一发,把storeVue里面的其他组件关联起来:

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import router from "./router";
import store from "./store";
Vue.config.productionTip = false
new Vue({
// render: h => h(App),
router,
store
}).$mount('#app')

然后components目录下面新建一个vuex.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template lang="html">
<div class="vuex">
<!-- 这个state相当于组件里面的data部分 -->
vuex {{ $store.state.count }}
<button type="button" name="button" @click="increment">增加</button>
<button type="button" name="button" @click="decrement">删除</button>
</div>
</template>
<script>
// 做了一次关联
import { mapActions } from "vuex";
export default {
methods: mapActions([
'increment',
'decrement'
])
}
</script>
<style lang="css">
</style>

然后在App.vue里面引入一波这个组件就可以了。

这样页面里面的出现两个点击的button,这样就可以去进行Vuex的数据交互了。

Vuex的高级用法

这里演示一波三个不同页面使用不同的store去进行状态管理。

干脆我们直接在src目录下新建一个store目录.

store/modules/a.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const state = {
money: 1
}
const mutations = {
add(state){
state.money ++;
},
reduce(state){
state.money --;
}
}
const actions = {
add: ({ commit }) => {
commit('add');
},
reduce: ({ commit }) => {
commit('reduce')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

同样也写个b.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const state = {
count: 10
}
const mutations = {
add(state){
state.count ++;
},
reduce(state){
state.count --;
}
}
const actions = {
add: ({ commit }) => {
commit('add');
},
reduce: ({ commit }) => {
commit('reduce')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

然后在一个公共的目录里面导出出去:

store/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from "vue";
import Vuex from "vuex";
import money from "./modules/a";
import count from "./modules/b";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
money,
count
}
})

main.js里面将storevue进行一个关联:

1
2
3
4
5
6
7
8
9
10
import Vue from 'vue'
import router from "./router";
import store from "./store/index";
Vue.config.productionTip = false
new Vue({
router,
store
}).$mount('#app')

然后老规矩去新建components/a.vue,注意观察这里在vuex里面拿数据和调用方法和之前的区别.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<div class="a">pages a {{$store.state.money.money}}</div>
<button type="button" name="button" @click="add">增加money</button>
<button type="button" name="button" @click="reduce">减少money</button>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
methods: mapActions('money',[
'add',
'reduce'
])
};
</script>
<style>
</style>

同样的b.vue也是类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<div class="b">
pages b {{ $store.state.count.count }}
</div>
<button type="button" name="button" @click="add">增加数量</button>
<button type="button" name="button" @click="reduce">减少数量</button>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
methods: mapActions('count',[
"add",
"reduce"
])
}
</script>
<style>
</style>

然后如果我们想在组件里面传递参数给vuex的话,以b.vue做个例子吧:

1
<button type="button" name="button" @click="add(2)">增加数量</button>

我们在这里传递了一个参数2,然后我们去b.js那边接收一波:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const mutations = {
add(state,payload) {
window.console.log(payload);
state.count+=payload;
},
reduce(state) {
state.count--;
},
};
const actions = {
add: ({ commit }, payload) => {
commit("add", payload);
},
reduce: ({ commit }) => {
commit("reduce");
},
};

这样就相当于完成了一个传递参数的过程。。。

-------------本文结束感谢您的阅读-------------