zoukankan      html  css  js  c++  java
  • 前端入职学习笔记-第二周第三天(vue组件传值:Bus传值、路由传值、Vuex传值)

    Bus总线

    1 定义Bus总线

      在main.js中定义Bus总线  

      const Bus = new Vue()

      然后将Bus添加到new Vue中的data里面  

      data: {
          Bus
       }

      Bus也可以定义在assets文件夹下的js文件中,需要用到时可以引入该文件,但是在webpack打包时,该文件会分解成多个Bus,从而报错,该方法不推荐使用。

    2 传值

      调用$root下的Bus,使用$emit函数在需要传值的组件中进行传值,且设置触发事件的字段"city" 

       this.$root.Bus.$emit("city"cityArr)

    3 接收值

      调用$root下的Bus,使用$on函数在需要接收值的组件中响应之前的"city"字段,从而在回调函数中接收传过来的值并进行后续操作。 

      this.$root.Bus.$on("city", (data=>{
            console.log(data);
            this.cityName = data[0]
            this.cityBool = data[2]
        })

      注意:回调函数最好使用箭头函数,不然this的指向会变向。

    Bus传值可能会出现组件销毁时,再次创建组件,之前的响应会被多次触发,可以在周期函数beforeDestroy中用this.$root.Bus.$off()来消除

    路由传值

    在需要传值的组件的router-link中设置需要传的值params

    <router-link class="movieLink" :to=" {name: 'movie'params: {hid: i}}">
    <h3>{{item.title}}</h3>
      <span>{{item.language}}</span>
      <p>{{item.actors | ellipsis(20)}}</p>
      <p>{{item.plot_simple | ellipsis(40)}}</p>
    </router-link>

    index.js中可以把路由附加上传的值hid

    {
      path: '/movie/:hid',
      name: 'movie',
      component: movie
    }

    在需要接受值的组件中调用传过来的值hid

    this.movieDeteil = res.data.result[this.$route.params.hid]

    Vuex传值

    安装vuex

    npm install vuex --save

    1.在src目录下新建store文件夹并在该文件夹下新建index.js文件。 在 store/index.js写入:

    复制代码
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
      strict:true,  // 开启严格模式  确保state 中的数据只能 mutations 修改
      state:{
        count:0
      }
    })
    
    export default store;
    复制代码

    在main.js中引入:

    复制代码
    import store from './store'

    new Vue({
    el: '#app',
    router,
    store,
    components: { App },
    template: '<App/>'
    })
    复制代码

    此时可以在组件中使用 this.$store.state.count 获取store中state的值。如:

    复制代码
    // 在组件的computed中使用
      computed:{
         count(){
          return this.$store.state.count;
         }
      }
    复制代码
    复制代码
    <template>
      <div class="hello">
        <h2>{{count}}</h2>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      computed:{
         count(){
           return this.$store.state.count;
         }
      }
    }
    </script>
    复制代码

    很多时候咱们要对state里的值进行操作,在vuex提供了一个方法mutations

    mutations用法(使用mutations可以修改state的值)

    在store/index.js中写入:

    复制代码
    //
    ...
      state:{
        count:0
      },
      mutations:{ // 更改数据的方法
        add(state){
          state.count++
        },
        //提交载荷用法
    //     add(state,n){  
    //      state.count += n
    //    },
        sub(state){
          state.count--
        }
      }
    ...
    //
    复制代码

    在组件中使用mutations中对应的方法

    复制代码
    <template>
      <div class="hello">
        <button @click="add">+</button>
        <h2>{{count}}</h2>
        <button @click="sub">-</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      computed:{
         count(){
           return this.$store.state.count;
         }
      },
        methods:{
        add(){
          this.$store.commit('add');
        },
        
        //提交载荷用法
       // add(){  
       //    this.$store.commit('add',10);
       // },
       
       //对象风格的提交方式
       //   store.commit({
       //     type: 'add',
       //     n: 10
       //     })
       
        sub(){
          this.$store.commit('sub');
        }
      }
    }
    </script>
    复制代码

    此时就可以对count进行修改了。

    补充1:mutation接收单个参数和多个参数

    利用$store.commit 里面 写参数相当于 mutation的函数名字

    复制代码
    在组件里面:
        第一种方式: this.$store.commit("addIncrement",{name:'stark',age:18,n:5})
        第二种方式:
        this.$store.commit({
            type:"addIncrement",
            n:5,
            age:18,
            name:'stark.wang'
        })
    复制代码

    在vuex里面接收:接收第二个参数相当于前面传过来的参数,如果多个这个就是对象,如果是一个参数,这个第二个参数payload就是前面的参数,例如

    复制代码
    let store = new Vuex.Store({
        state: {
            num: 100
        },
        mutations: {
            // 任何时候改变state的状态都通过提交 mutation 来改变
            // 里面可以定义多个函数,当触发这个函数就会改变state状态
            addIncrement(state, stark) {
                console.log(stark);
                // 接收一个state作为参数, 相当于上面的state
                 // 在vuex里面接收:接收第二个参数相当于前面传过来的参数,如果多个这个就是对象,如果是一个参数,这个第二个参数payload就是前面的参数。
                // mutations设计原则是同步的
                //state.num += stark;
                state.num += stark.n;
            
    
            },
            minIncrement(state) {
                state.num -= 5;
            }
        }
    
    })
    复制代码

     补充2:遇到在组件input中直接修改state中数据的问题

    在组件中写入

    复制代码
    <div class="form-control amis-control">
      <input name="name" placeholder="" type="text" autocomplete="off" :value="activeFormData.title" @input="updataMessage($event,'t1.title')">
    </div>

    <script>
    ...
    computed:{
      activeFormData(){
        return this.$store.state.formData.t1
      }
    },
    methods:{
      updataMessage(e,dataposition){
        let newposition = dataposition.split('.);
        this.$store.commit('updataMessage',{newval:e.target.value,curposition:newposition})
      }
    }
    </script>  
    复制代码

    在store.js中写入

    复制代码
    mutations:{
      ...
      updataMessage(state, stark) {
          if (stark.curposition.length == 2) {
            state.formData[stark.curposition[0]][stark.curposition[1]] = stark.newval
          } else if (stark.curposition.length == 3) {
            state.formData[stark.curposition[0]][stark.curposition[1]][stark.curposition[2]] = stark.newval
          }
    
        },  
    }
    复制代码

    当你想异步操作的时候,由于mutation必须是同步的这一点,此时不能采用mutation对state 进行修改。action派上用场了,action就是一个函数集合,在里面怎么操作都可以,只要最后触发mutation 就可以了。

    复制代码
    注解mutation不能异步操作的原因:
    
     mutations: {
       add (state) {
         api.callAsyncMethod(() => {
        state.count++
       })
      }
    }
    复制代码
    现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。
     

    Action 用法

    在store/index.js中写入

    复制代码
      mutations:{ // 更改数据的方法
        add(state){
          state.count++
        },
        sub(state){
          state.count--
        }
      },
    ++++
      actions:{
        addAction(context){  // context 与 store 实例具有相同方法和属性(但不是store 实例)
          setTimeout(()=>{
            context.commit('add');
          },1000)
        }
      }
    ++++
    复制代码

    组件中使用getters里对应的方法:

    复制代码
    <template>
      <div class="hello">
        <button @click="add">+</button>
        ++++
        <button @click="add_action">action +</button>
        ++++
        <h2>{{count}}</h2>
        <button @click="sub">-</button>
        <div>
          test: {{doneTodos[0].text}} <br>
          length: {{doneTodosLength}}
        </div>
      </div>
    </template>
    export default {
      methods:{
        add(){
          this.$store.commit('add');
          // console.log(this);
        },
        sub(){
          this.$store.commit('sub');
        },
        ++++
        add_action(){
          this.$store.dispatch('addAction');
        }
        ++++
      }
    }
    复制代码

    实际异步操作

    组件methods中:

    在store/index.js中引入axios :

    import axios from 'axios'

    看到这里有没有想过当我们使用state中某一个数据时,我们只想用该数据中符合条件的数据。比如:

    复制代码
    state:{
        count:0,
        todos: [
          { id: 1, text: 'text1--true', done: true },
          { id: 2, text: 'text2--false', done: false }
        ]
      }
    复制代码
    此时我们只想获取state.todos中done为true的数据时我们应该怎么获取?
    可能会有以下两种方案:
    1.每个在组件中首先获取todos,然后使用filter方法过滤;
    2.写一个公共函数在每个组件中调用以下;
    如果用到todos中done为true的组件很多,这两种方法都是很不理想的。Vuex为此为我们引入了一个方法Getter。
     

    Getter 用法

    官方解释:Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

    在storeindex.js写入:
    复制代码
      mutations:{ // 更改数据的方法
        add(state){
          state.count++
        },
        sub(state){
          state.count--
        }
      },
      +++
      getters:{  // 用法类似组件中的 computed, 可以认为是store的计算属性
        doneTodos:state => { // Getter 接受 state 作为其第一个参数:
          return state.todos.filter(todo => todo.done)  // -> [{ id: 1, text: 'text1--true', done: true }]
        },
        // Getter 也可以接受其他 getter 作为第二个参数
        doneTodosLength:(state,getters) => {
          return getters.doneTodos.length // -> 1
        },
      +++
      }
    复制代码

    在组件中使用getter对应的方法:

    复制代码
    <template>
      <div class="hello">
    
        <button @click="add">+</button>
        <h2>{{count}}</h2>
        <button @click="sub">-</button>
    
    +++
        <div>
          test: {{doneTodos[0].text}} <br>
          length: {{doneTodosLength}}
        </div>
    +++    
      </div>
    </template>
    <script>
    export default {
      //...
        computed:{
        +++
            doneTodos(){
              return this.$store.getters.doneTodos // -> [{ id: 1, text: 'text1--true', done: true }]
            },
            doneTodosLength(){
              return this.$store.getters.doneTodosLength // -> 1
            }
        +++
      }
    }
    </script>
    复制代码

    详细可参考:vue组件通信传值——Vuex

    Vue使用webpack打包步骤:

    修改请求静态资源的路径
    打开config下的index.js文件,修改assetsPublicPath的值,从‘/’改为‘./’。即从根路径改为相对路径。

    build: {
        // Template for index.html
        index: path.resolve(__dirname, '../dist/index.html'),

        // Paths
        assetsRoot: path.resolve(__dirname, '../dist'),
        assetsSubDirectory: 'static',
        assetsPublicPath: './',
     }

    修改本地图片的路径
    打开build下的utils.js文件,增加 publicPath:'../../'

    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        publicPath:'../../'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

     在终端运行npm run build。

  • 相关阅读:
    java学习 接口与继承11 默认方法
    java学习 接口与继承10 内部类
    java学习 接口与继承9 抽象类
    java学习 接口与继承8 final
    理解管理信息系统
    vue中的错误日志
    vue中的ref属性
    2.有24颗外观完全一样的小球,其中有一个是空心的,现在只有一个天平,最少称几次能找出这个特殊的球?
    1.有888瓶编了号码的水及10只健康的小白鼠,其中一瓶水有毒,小白鼠饮用毒水一天后会死,最少需要几天可以找到哪瓶水有毒?
    SQL题1两表联查
  • 原文地址:https://www.cnblogs.com/kyrie1/p/13361118.html
Copyright © 2011-2022 走看看