今天我们要来利用模组化后的Vue来进行一些操作。
而组件的基本架构如下:
<template> 模板<h1 class="title"> {{ ... }}</h1></template><script> 程式export default { name:"titleData",}</script><style> 样式</style>
首先我们想要创建一个能够显示Title的组件。
第一步就是要在App.vue中先引入他。
// 要将component渲染到画面上,首先要import进App.vue import Title from './components/Title.vue'
接着挂载在我们的components
components: { HelloWorld, Title, },
最后将引入的组件加至template中。
<template> <div id="app"> <Title titleData="hello jojo"/> <HelloWorld msg="Welcome to Your Vue.js App" /> </div></template>
而我们在Title的组件中也要做一些处理。
模板的部分:
<template><h1 class="title"> {{ titleData }}</h1></template>
程式的部分:data部分要用func型式
,而不是物件(include作法),因为component会共用
,如果直接做物件出来,每个component都会包到同一包资料,也就是会互相影响。
<script>export default { name:"titleData", data() { return { title:"hello jojo" } },<script>
而每一个组件都是独立的,我们无法直接从子组件获取父组件的资料
,而我们现在只想要这个模组显示资料
,而不用包含资料
,也就是说资料是从父层传过来
,就要透过Props,而Props是单向的,只会从父层传至子层,Props 的值也会因父层改变而改变。
<script>export default { name:"titleData", // data() { // return { // title:"hello jojo" // } // },// 接收从外部(App.vue的 <Title/>)传进来的资料titleData="hello jojo"// 记得template中的资料也要改成titleData props:{ // 给我一个titleData titleData:{ // 类型是字串 type:String, // required就是一定要 required:true } }}</script>
样式的部分:
为了不影响到其他组件
,我们可以使用scoped,scoped可以将样式封装在当前模组
,尽量不要直接搭配tag,要加上class,id,否则效能会较差,如果不加上scoped就会影响到其他component。
<style scoped> h1.title { color:#fa5 }</style>
加上scoped前(上图),加上后(下图)。
而在App.vue的部分,我们除了可以直接传递资料外。
<template> // 利用直接传递资料的方法 <Title titleData="hello jojo"/></template>
也可以利用绑定的方式来传递我们的资料,记得要将我们所要绑定的资料,在data函数中将值设置进去。
<template> // 利用资料绑定的方法传递资料 <Title :titleData="bindData"/></template> export default { name: 'App', data() { return { bindData:"this is a bind msg" } },
除此之外,我们这边再做一个input的组件,且当输入框改变,画面的资料也会同步跟着改变,而这个组件我们先创建一个资料夹,并分别创建template,vue,css。
然后在父组件,按照创建组件的流程,引入组件、挂载组件、最后在套用组件。
将资料(bindData)传入至子组件。
<InputComponent :text="bindData"/>
而在子组件我们利用props接收父组件传入的资料。
export default { name:"input-component", // 获取的属性及值 props:{ text:{ type:String, required:true } }}
template部分
<input type="text" v-model="text">
而后当我们改变input的值,会发现报错,因为直接从子组件改变外部资料是不允许的,也就是说我们不能更动原资料
(App.vue父层),因此我们写一个computed来改变子层资料,并同步更新父层资料
。
computed的属性可以被视为像是 data 一样,可以读取和设值,因此在computed中分成getter(读取)
和setter(设值)
,在没有写 setter 的情况下,computed 预设为 getter
,也就是只能读取,不能改变设值
,getter
在大部分的时候是当内部观察的资料有改变时会被触发
;setter 则是当被观察的物件本身有改变时会被触发
,也就是当我们改变输入框的值时。
而在setter部分,可透过emit将子组件的资料传递至父组件
,这边我们传递一个事件textChange,并传递一个value
(子组件input当前的值)。
computed: { inputText:{ // 获取值 get(){ console.log("get"); return this.text }, // 设置值 set(value){ console.log(value) // 子组件与父组件沟通的桥樑 // this.$emit('event', […args]) this.$emit('textChange', value) } } },
记得在template将绑定从 v-model="text" 改成inputText也就是我们包含两个函数的 computed。
<input type="text" v-model="inputText">
子组件设置完成后,我们再回到父组件,接收从子层传来的事件,并加上一个函数处理传来的值。
<InputComponent :text="bindData" @textChange="changeHandler" />
methods中处理子组件传来的值,将其同步到父组件的资料。
methods: { // 处理子层传来的值(input中的值) changeHandler(value){ // 将input中的值同步改变 bindData中的值 this.bindData = value } },
而我们打开Vue Devtools,可发现我们的子组件本身都没有资料,那资料在哪里呢?都统一放在我们的父组件做管理,分给其他子组件使用,所以当我们在子组件改变输入框的值,他会呼叫外部的资料,也就是父层的资料也进行改变,而父层的资料又会同步更新到画面上。