Vue框架使用小结

从三个部分复习:

  • 基本使用、组件使用
  • 高级特性
  • Vuex和Vue-router使用

一、Vue使用

1.vue基本使用

vue基本使用不会还找什么工作?在这就梳理一下知识点

(1)指令插值

插值表达式 动态属性 v-html
<template>
    <div>
        <p>文本插值 {{message}}</p>
        <p>JS 表达式 {{flag?'yes':'no'}}//(只能是表达式,不能是 js 语句)</p>

        <p :id="dynamicId">动态属性 id</p>

        <hr/>
        <p v-html="rawHtml">
            <span>有 xss 风险</span>
            <span>【注意】使用v-html之后,将会覆盖子元素</span>
        </p>
        <!-- 其他常用指令后面讲 -->
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: 'hello vue',
            flag: true,
            rawHtml: '指令-原始html <b>加粗</b> <i>斜体</i>',
            dynamicId: `id-${Date.now()}`
        }
    }
}
</script>

(2)computed watch

computed有缓存,data不变,则不会重新计算
<template>
    <div>
        <p>num {{num}}</p>
        <p>double1 {{double1}}</p>
        <input v-model="double2"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 20
        }
    },
    computed: {
        double1() {
            return this.num * 2
        },
        double2: {//double2是被双向绑定的 所以一定要设置get set两个方法
            get() {
                return this.num * 2
            },
            set(val) {
                this.num = val/2
            }
        }
    }
}
</script>
watch
聆听引用类型的时候要深度聆听,而且拿不到引用类型的OldVal
使用handler进行深度聆听 可以监听到数组、对象的变化 不然无法聆听到引用类型内部的变化
//深度监听代码
watch:{
    b:{
        handler(val,oldVal){
            return ''
        },
            deep:true//true 深度监听
    }
}
<template>
    <div>
        <input v-model="name"/>
        <input v-model="info.city"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '双越',
            info: {
                city: '北京'
            }
        }
    },
    watch: {
        name(oldVal, val) {
            // eslint-disable-next-line
            console.log('watch name', oldVal, val) 
          // 值类型,可正常拿到 oldVal 和 val
        },
        info: {
            handler(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch info', oldVal, val) 
                   // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
            },
            deep: true // 深度监听
        }
    }
}
</script>

(3)class和style

使用动态属性 使用驼峰式写法
<template>
    <div>
        <p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
        <p :class="[black, yellow]">使用 class (数组)</p>
        <p :style="styleData">使用 style</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }
}
</script>

<style scoped>
    .black {
        background-color: #999;
    }
    .yellow {
        color: yellow;
    }
</style>

(4)条件渲染

<template>
    <div>
        <p v-if="type === 'a'">A</p>
        <p v-else-if="type === 'b'">B</p>
        <p v-else>other</p>

        <p v-show="type === 'a'">A by v-show</p>
        <p v-show="type === 'b'">B by v-show</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            type: 'a'
        }
    }
}
</script>
v-if v-else可以使用变量 也可以使用===表达式
注意区分v-if 和 v-show
v-if渲染的结果只有一个 但是v-show会渲染出所有条件,只不过把不符合条件的设为style="display:none"
如果是频繁的切换,那么v-show更加合适 一次性选择v-if就够用

(5)循环列表渲染

<template>
    <div>
        <p>遍历数组</p>
        <ul>
            <li v-for="(item, index) in listArr" :key="item.id">
                {{index}} - {{item.id}} - {{item.title}}
            </li>
        </ul>

        <p>遍历对象</p>
        <ul>
            <li v-for="(val, key, index) in listObj" :key="key">
                {{index}} - {{key}} -  {{val.title}}
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data() {
        return {
            flag: false,
   //数据结构中,最好有id 方便使用key

            listArr: [
                { id: 'a', title: '标题1' }, 
                { id: 'b', title: '标题2' },
                { id: 'c', title: '标题3' }
            ],
            listObj: {
                a: { title: '标题1' },
                b: { title: '标题2' },
                c: { title: '标题3' },
            }
        }
    }
}
</script>
使用v-for也可以遍历对象
key很重要,但key不能乱写
注:v-for v-if不能一起使用!!!

(6)事件

<template>
    <div>
        <p>{{num}}</p>
        <button @click="increment1">+1</button>
        <button @click="increment2(2, $event)">+2</button>
               //这里写了什么参数 下面接收就行了
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 0
        }
    },
    methods: {
        increment1(event) {
            // eslint-disable-next-line
            console.log('event', event, event.__proto__.constructor) 
                      // event是MouseEvent 就是一个原生的 event 对象
            // eslint-disable-next-line
            console.log(event.target)
            // eslint-disable-next-line
            console.log(event.currentTarget) 
                     // 注意,事件是被注册到当前元素的,和 React 不一样
            this.num++
                         //一些结论
            // 1. event 是原生的
            // 2. 事件被挂载到当前元素
            // 和 DOM 事件一样
        },
        increment2(val, event) {
            // eslint-disable-next-line
            console.log(event.target)
            this.num = this.num + val
        },
        loadHandler() {
            // do some thing
        }
    },
    mounted() {
        window.addEventListener('load', this.loadHandler)
    },
    beforeDestroy() {
        //【注意】用 vue 绑定的事件,组建销毁时会自动被解绑
        // 自己绑定的事件,需要自己销毁!!!
        window.removeEventListener('load', this.loadHandler)
    }
}
</script>
event是一个原生的event对象,没有经过任何的修饰
并且,event的target和currentTarget是相同的
(记住 要和React做对比)
一些很方便的事件修饰符

还有很方便的按键修饰符

(7)表单

<template>
    <div>
        <p>输入框: {{name}}</p>
        <input type="text" v-model.trim="name"/>
        <input type="text" v-model.lazy="name"/>
        <input type="text" v-model.number="age"/>

        <p>多行文本: {{desc}}</p>
        <textarea v-model="desc"></textarea>
        <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

        <p>复选框 {{checked}}</p>
        <input type="checkbox" v-model="checked"/>

        <p>多个复选框 {{checkedNames}}</p>
        <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
        <label for="jack">Jack</label>
        <input type="checkbox" id="john" value="John" v-model="checkedNames">
        <label for="john">John</label>
        <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
        <label for="mike">Mike</label>

        <p>单选 {{gender}}</p>
        <input type="radio" id="male" value="male" v-model="gender"/>
        <label for="male">男</label>
        <input type="radio" id="female" value="female" v-model="gender"/>
        <label for="female">女</label>

        <p>下拉列表选择 {{selected}}</p>
        <select v-model="selected">
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>

        <p>下拉列表选择(多选) {{selectedList}}</p>
        <select v-model="selectedList" multiple>
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '双越',
            age: 18,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
}
</script>
表单使用考察的可能性不大 但是实际中真的很常用哈 记住表达都用v-model来双向绑定

2.组件通讯

首先,把实例代码放出来

父组件 index.vue

<template>
    <div>
        <Input @add="addHandler"/>//聆听add事件 并接收到子组件传来的this.title
        <List :list="list" @delete="deleteHandler"/>
                //在这两个子组件上 聆听两个事件
    </div>
</template>

<script>
import Input from './Input'
import List from './List'

export default {
    components: {
        Input,
        List
    },
    data() {
        return {
            list: [
                {
                    id: 'id-1',
                    title: '标题1'
                },
                {
                    id: 'id-2',
                    title: '标题2'
                }
            ]
        }
    },
    methods: {
        addHandler(title) {
            this.list.push({
                id: `id-${Date.now()}`,
                title
            })
        },
        deleteHandler(id) {
            this.list = this.list.filter(item => item.id !== id)
        }
    }
}
</script>

子组件input

<template>
    <div>
        <input type="text" v-model="title"/>
        <button @click="addTitle">add</button>
            //聆听click事件 触发addTitle
    </div>
</template>

<script>
import event from './event'

export default {
    data() {
        return {
            title: ''
        }
    },
    methods: {
        addTitle() {
            // 向外触发add事件 并传递this.title
            this.$emit('add', this.title)

            // 调用自定义事件
            event.$emit('onAddTitle', this.title)

            this.title = ''
        }
    }
}
</script>

子组件List

<template>
    <div>
        <ul>
            <li v-for="item in list" :key="item.id">
                {{item.title}}

                <button @click="deleteItem(item.id)">删除</button>
                              //同理 触发deleteItem函数 并传递参数
            </li>
        </ul>
    </div>
</template>

<script>
import event from './event'

export default {
    // props: ['list']
    props: {
        // prop 类型和默认值
        list: {
            type: Array,
            default() {
                return []
            }
        }
    },
    data() {
        return {

        }
    },
    methods: {
        deleteItem(id) {
            this.$emit('delete', id)
        },//向外触发delete事件并传递参数
        addTitleHandler(title) {
            // eslint-disable-next-line
            console.log('on add title', title)
        }
    },
    mounted() {

        // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)
    },
    beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }
}
</script>

(1)props $emit

父组件给子组件传值:
如上面实例中的index给List组件传递list这个数组——通过v-bind给子组件绑定属性,子组件通过props接收后使用
注:props接收数据有几种不同的写法
props:[list]//最简单的写法
props:{
    list:{
        type:Array,
        default() {
            return []
        }
    }
}//复杂一些 指定类型和默认值
props:{
    list:Array
}//只指定类型
子组件给父组件传值:如上面实例
首先,要在父组件中聆听事件,并写methods函数  子组件发生点击这些简单事件时 ,会在事件处理程序中调用this.$emit( )向外触发事件
this.$emit('delete', id)//delete 父组件聆听的事件 id子组件给父组件传递的值
说白了,this.$emit有点类似事件冒泡,但它在冒泡途中,进行了一些包装,等到了父组件的时候,变了一个模样。它不能像冒泡那样自然进行,而是子组件上触发的事件,通过this.$emit去触发父组件上的另一个事件。父组件再调用对应的事件处理程序,就实现了——子组件改变父组件的值。

(2)兄弟组件通讯

兄弟组件通讯有两种思路:

一是之前在去哪儿网项目里用到的:https://blog.nowcoder.net/n/8dfaf3ba5eb847cea7cdcd9bcb40f06e
思路是:子组件1——>父组件——>子组件2
这里就copy一下之前写的——实现点击字母表 城市list就滚动到对应的数字
思路:对字母表组件绑定一个点击事件 父组件获得每次点击时的字母值 并将这个字母值传递给List组件
即  兄弟组件传值:字母表——>City.vue——>List.vue
1.对字母表组件 绑定一个点击事件

2 每次点击都向外触发事件change

3.在City.vue中监听事件change

change事件触发函数 handleLetterChange 获取letter的值

以属性的形式 获取传来的值 并传给List.vue

List.vue接收

4.在List接收到传来的Letter值后,当字母值改变,List的显示也应该改变 也就是通过watch 实现:
给每个字母绑定ref

获取$refs这个数组的第一个值(即当前字母项)使用scroll插件的函数实现跳转效果
取  第[0]项 是因为此时的$refs[this.letter]是一个数组 但是scroll方法使用的必须是元素。 
取[0]值 便取到了真正的元素  使用watch 滚动到对应的界面

思路二 是新学得 通过自定义事件进行传值
这个思路非常干脆,不但能用在兄弟组件上,还能用在离得很远的组件上
以todolist为例
在list组件上绑定一个自定义事件
 mounted() {
        // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)
    },
该事件调用list中的方法addTitleHandler
methods: {
        addTitleHandler(title) {
            // eslint-disable-next-line
            console.log('on add title', title)
        }
    }
在input组件中聆听点击事件 被点击后调用addTitle事件处理程序
<button @click="addTitle">add</button>
而在addTitle中  调用了自定义事件onAddTitle
 methods: {
        addTitle() {
            // 调用自定义事件
            event.$emit('onAddTitle', this.title)

            this.title = ''
        }
list组件中的 addTitleHandler方法因为被调用
要注意:this.$emit 和 event.$emit之间的区别
event值得是单独创建的一个Vue实例 

											
											
											
											
  1. import Vue from 'vue'
  2. export default new Vue()
因此,list组件和input组件在使用event.$emit时,都要先引入event
import event from './event'

最最重要的一点 及时销毁自定义的event事件 !
 beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }

(3)组件生命周期

单个组件的生命周期

挂载阶段
beforeCreate
created——此时VUE实例已经初始化结束 但还没有渲染
beforeMount
mounted——此时已经渲染结束
更新阶段
beforeUpdate
updated
销毁阶段
beforeDestroy——解除绑定  销毁啊子组件 以及watch
destroyed
带有父子组件的生命周期
还是todolist的例子:

  • created:先创建父组件 再创建子组件
  • mounted:先渲染子组件 再渲染父组件
  • beforeUpdate:先预备更新父组件 再预备更新子组件
  • Updated:先更新子组件 再更新父组件
  • beforeDestroy:先预备销毁父组件 再预备销毁子组件
  • Destroyed:先销毁子组件 再销毁父组件

3.Vue高级特性

不是很常用,但是用的时候必须要知道
自定义v-modle
$nextTick
slot
动态、异步组件
keep-alive
mixin

(1)自定义v-modle

在父组件,使用双向数据绑定:<CustomVModel v-model="name"/>
   <div>
        <!-- 自定义 v-model -->
        <<p>{{name}}</p>
        <CustomVModel v-model="name"/> 
   </div>
//CustomVModel 
<template>
    <!-- 例如:vue 颜色选择  在v-model输入色号 就能显示出来颜色-->
    <input type="text" 
           :value="uname" 
           @input="updateVal($event.target.value)">

    <!--
        1. 上面的 input使用的是动态属性:value 而不是 v-model
        2. 上面的 change 和 model.event 要对应起来
        3. 上面的text1属性和下面的text1要对应起来
    -->
</template>

<script>
export default {
model: {
        prop: 'uname',
        // 随便命名事件,对应下面$emit即可
        event: 'changeXXX'
    },
    props: {
        uname: {
            type: String,
            default: 'tom'
        }
    },
    methods: {
        updateVal(val){
            this.$emit('changeXXX',val)
        }
}
</script>
上面代码定义了一个methods来触发事件,和下面这段代码的@input="$emit('change1', $event.target.value) 一个意思
<template>
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
</template>

<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>
关于v-model的深入理解可以参考:https://blog.csdn.net/liu_jun_tao/article/details/90232658
下面做一些关于这篇文章的摘录和思考:
现成的v-model也是一个语法糖,它内里真正的实现形式是:
<input type="text" 
       :value="message" 
       @input="message = $event.target.value">
  • 将输入框的值绑定到message变量上,这只是单向的,改变message的值可以改变input的value,但是改变input的输入还不能改变message。
  • 监听input事件,当输入类内容时改变message变量,从而实现了双向绑定。
也就是说,在默认情况下,v-model把value值当作prop input当作event
所以,在我们自定义v-model组件时,就需要显示的来声明这些默认的定义,也就是我们在model选项内声明:
    model: { //重点就是这里哈
        prop: 'name', // prop的值
        event: 'change'//聆听的事件
    }

(2)$nextTick

首先,要记住Vue是异步渲染的框架 在data改变之后 DOM并不会立刻渲染
而$nexiTick会在DOM渲染之后被触发,以获取最新的DOM节点
<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">添加一项</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    addItem() {
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)

        // Vue是异步渲染,而$nextTick在DOM渲染完才回调 
                //所以可以通过$nextTick拿到最新的结果
        // 上端代码修改了三次 但页面渲染时会将data的修改做整合
               //随意,最终多次data修改只会渲染一次 这也只有异步能够实现
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
</script>
这里包含的小知识点:
在vue中想要拿到DOM元素
就给该标签设置ref属性 <ul ref="ul1">
通过this.$ref.ul1就可以获取该标签的DOM节点

(3)slot

插槽,也就是父组件要往子组件里插点什么

基本使用
//父组件中
<SlotDemo :url="website.url"
{{website.title}}
</SlotDemo>

//子组件中
<template>
    <a :href="url">
        <slot>
            默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
}
</script>
把父组件中的website.title 通过<slot> 插入到子组件中
非常简单
作用域插槽
//父组件中
<SlotDemo :url="website.url"
            <template v-slot="slotProps">//就是多搞一个template
           {{slotProps.slotData.title}}
            </template>

</SlotDemo>

//子组件中
<template>
    <a :href="url">
       <slot :slotData="website">//就是增加一个:slotData属性
    {{website.subTitle}} //父组件不传内容时显示 '轻量级富文本编辑器'
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '轻量级富文本编辑器'
            }
        }
    }
}
</script>
简单地说
基本使用时是把父组件的内容插到子组件里
作用域插槽就是子组件非得想用自己的内容 要在父组件里显示自己的
具名插槽

(4)动态组件

用法———— :is = "component-name"
适用于需要根据数据,动态渲染的场景,即组件类型不确定的时候  比如一个新闻页面 text /image /video 各个组件的顺序是不一定的,无法确定,这个时候就需要动态组件啦
<template>
    <div v-for="(val,key) in newsData" :key="key">
        <component :is="val.type">//动态组件
</template>
<script>
export default{
data() {
return {
newsData:{
    1:{type:'text'},
    2:{type:'text'},
    3:{type:'image'}
}}}}
</script>

(5)*异步组件

常见!常考!
实际开发中,经常有很多体积较大的组件,对于这些大组件就要使用异步组件。什么时候用什么时候加载
异步组件引入时不用import 而是在component组件注册中引入:
components:{
    FormDeom:() => import ('...路径')
}

(6)缓存组件

用keep-alive缓存组件 适用于频繁切换,不需要重复渲染的场景 也是Vue中常见的性能优化方法
例子:
如果不用keep-alive 由A切换为B的时候,A就会被destroy 
使用keep-alive 谁都不会被destroy 切换时也不用重新渲染 
这里就要和v-show做个对比:
v-show是通过原生的CSS中的display=none来控制 适用于非常简单的情况
而keep-alive是在框架层次做JS的渲染
<template>
    <div>
        <button @click="changeState('A')">A</button>
        <button @click="changeState('B')">B</button>
        <button @click="changeState('C')">C</button>

        <keep-alive> <!-- tab 切换 -->
            <KeepAliveStageA v-if="state === 'A'"/> 
            <KeepAliveStageB v-if="state === 'B'"/>
            <KeepAliveStageC v-if="state === 'C'"/>
        </keep-alive>
    </div>
</template>

<script>
import KeepAliveStageA from './KeepAliveStateA'
import KeepAliveStageB from './KeepAliveStateB'
import KeepAliveStageC from './KeepAliveStateC'

export default {
    components: {
        KeepAliveStageA,
        KeepAliveStageB,
        KeepAliveStageC
    },
    data() {
        return {
            state: 'A'
        }
    },
    methods: {
        changeState(state) {
            this.state = state
        }
    }
}
</script>

(7)mixin

当多个组件有相同的逻辑时,使用mixin可以抽离出共同逻辑
<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">显示姓名</button>
    </div>
</template>

<script>
import myMixin from './mixin'

export default {
    mixins: [myMixin], // 可以添加多个,会自动合并起来
    data() {
        return {
            name: '双越',
            major: 'web 前端'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}
</script>
myMixin代码:
export default {
    data() {
        return {
            city: '北京'
        }
    },
    methods: {
        showName() {
            // eslint-disable-next-line
            console.log(this.name)
        }
    },
    mounted() {
        // eslint-disable-next-line
        console.log('mixin mounted', this.name)
    }
}
说白了,mixins就是一个引用,把多个组件公用的方法函数放在mixin中,然后在使用时进行引入
但mixin也存在不少问题,比如可能造成命名冲突啊

(8)Vuex知识点

之前在去哪儿网项目里做非兄弟组件传值时用过了Vuex

理念:把公用的数据放在一个仓库里 从而实现读取和改变(整个流程是单向的)
Vuex的核心是store 可以简单的把store看作是一个仓库
state
是一个单一状态数
可以看作是所有组件公用的data 保存了公共数据
getters 可以理解为store的计算属性
actions
和mutatiohs类似 不同在于
  • actions提交的是mutations 而不是直接变更状态
  • actions中可以包含异步操作,默认的就是异步,并返回promise, mutations中绝对不允许出现异步
  • actions中的回调函数的第一个参数是context, 是一个与store实例具有相同属性和方法的对象
mutations
可以理解为store的methods 保存着更改数据的回调函数
其包含两个参数: 第一个参数是state, 第二参数是payload
Modules
就是store的模块化
用于Vue组件
dispatch 含有异步操作,例如向后台提交数据,写法: this.$store.dispatch('action方法名',值)
commit 同步操作,写法:this.$store.commit('mutations方法名',值)
mapState
这几个map前缀的可以说就是映射
在没有mapState的时候 引入state 需要 this.$store.state.xxx 
有了mapState以后 直接
import {mapState} from 'vuex'
export default {
  name: 'home',
  computed: ...mapState(['nickname','age','gender'])
}
咔咔的 就映射过来了
mapGetters 同理
mapAcionts
映射到methods里
methods:{
  ...mapActions(['getUserInfo'])
}
mapMutations
映射到methods里 参数可以在调用方法时在吸写入
methods:{
 ...mapMutations(['addAge'])
}

注意:在Actions里才能做异步操作 
为了加深理解,这里把之前项目中的代码copy一下
——————————————————————————————————————————
使用store中的数据
通过store.state使用存储的数据
1.在 src下 创建store(仓库)

写index.js
(Vue)里在使用插件都是用Vue.use来实现的
导出Vuex创建的Store
仓库里面有个state 存储着全局公用的数据

2.在main中引入store

在创建根实例时传入store

3.在需要使用公共数据的组件里使用 


改state中的数据

要实现List和Search中点击城市 就改变公共数据中city的值
1.首先以List组件为例
增加click事件 调用方法 传入此时的值

组件事件的处理程序调用 dispatch 方法 dispath执行对象就是Actions


2.在store的index文件中 创建名为changeCity的actions:
ctx表示上下文 并用用ctx调用commit commit执行对象是mutations

3.创建名为changeCity的mutations
在这个mutations中写入方法 改变state数据

所以,修改数据的整个流程为:
组件内使用Dispatch方法,调用Actions
Actions使用commit方法,调用Mutations
mutations内修改state数据
时刻记着这张图!在dispatch后的操作都是在store内进行的

——————————————————————————————————————————
找到了一个比较通俗易懂的文章 可以参考一下:https://www.jianshu.com/p/120eaf50331c

(9)Vue-router


之前项目用路由配置时的代码copy一下:
step1:
在路由配置文件里添加配置
需要import City

step2:找到需要跳转页面的子块 添加router-link 和 to 属性 就能跳转到City这个组件了
————————————————————————————————

路由模式
hash模式
H5 history
H5需要serve端配合
路由配置
动态配置:
懒加载:和之前异步组件非常类似



全部评论

相关推荐

昨天 17:11
已编辑
广东工业大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务