初学vue

156 阅读1分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

这篇文章是我毕业后,刚接触vue,最初学习vue2.x的时候记录的一些tip。

一、路由:

两种路由跳转方式:

  • this.$router.push({name: 'userAdd',params: {'id: row.id',}}): 地址栏不可见,安全性高,但是刷新之后参数会丢失, 通过this.$route.params.id获取页面传参。
  • this.$router.push({path: '/userAdd',query:{'id: row.id',}}):地址栏不可见,安全性不高,通过this.$route.query.id获取参数 其余路由跳转
  • this.$router.back(-1)等同于this.$router.go(-1)
  • this.$router.replace ,跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面
  • this.$router.go(n) ,向前或者向后跳转n个页面,n可为正整数或负整数,this.$router.go(1) 等同于 history.forward()

二、生命周期

beforeCreate
created (在模板渲染成html或者模板编译进路由前调用created)
beforeMount
mounted(已完成模板渲染或el对应html渲染后)
beforeUpdate
updated
beforeActivated: 缓存组件失活时调用
deactivated: 缓存组件被激活时调用
beforeDestroy
destroyed
errorCaptured: 2.5.0+新增

三、vue实例的属性

  • methods方法:定义方法
  • computed计算属性:在html DOM加载完成后执行
  • watch监听属性

四、组件slot 插槽:默认插槽|单个插槽|匿名插槽

  • 默认插槽
    1. 除了在index.js路由中添加子组件,在父组件中也需要定义子组件

      <template>
          <div class="slot_parent">
              <h1>这里是slot_parent</h1>
              <child>
                  <div>
                      <span>菜单1</span>
                      <span>菜单2</span>
                      <span>菜单3</span>
                      <span>菜单4</span>
                  </div>
              </child>
          </div>
      </template>
      
      <script>
      import child from './child'
      export default {
          name: 'slot_parent',
          components: {child}
      }
      </script>
      
    2. 在子组件中,使用<slot>引入父组件定义的菜单

      <template>
         <div class="child">
             <h2>这里是slot_child</h2>
             <slot></slot>    
         </div>    
      </template>
      
      <script>
      export default {
          name: 'child',
      }
      </script>
      
  • 具名插槽
    1. 在子组件中为<slot>添加name属性
      <template>
          <div class="child">
              <h2>这里是slot_parent_up</h2>
              <slot name="up"></slot>
              <h2>这里是slot_parent_down</h2>
              <slot name="down"></slot>
          </div>    
      </template>
      
    2. 在父组件中添加slot属性
      <template>
          <div class="slot_parent">
              <h1>这里是slot_parent</h1>
              <child>
                  <div slot="up">
                      <span>菜单1</span>
                      <span>菜单2</span>
                      <span>菜单3</span>
                      <span>菜单4</span>
                  </div>
                  <div slot="down">
                      <span>菜单5</span>
                      <span>菜单6</span>
                      <span>菜单7</span>
                      <span>菜单8</span>
                  </div>
              </child>
          </div>
      </template>
      
  • 作用域插槽|带数据的插槽
    1. 在父组件中用slot-scope绑定user数据,之后输出数据,数据在子组件中定义
      <template>
          <div class="slot_parent">
              <h1>这里是slot_parent</h1>
              <child>
                  <template slot-scope="user">
                      <ul>
                          <li v-for="item in user.data">{{item}}</li>
                      </ul>
                  </template>
              </child>
          </div>
      </template>
      
    2. 在子组件,slot中用:data绑定数据,并定义好数据
      <template>
          <div class="child">
              <slot :data="data"></slot>
          </div>    
      </template>
      
      <script>
      export default {
          name: 'child',
          data: function(){
              return {
                  data: ['张三','李四','王五']
              }
          }
      }
      </script>
      

五、组件之间的传值:

  • 父组件-->子组件(通过props向子组件传参)
    1. 通过:name=""绑定参数
      <template>
          <div class="parent">
              <son :logo='logomsg'></son>
              <router-view />
          </div>
      </template>
      
    2. 子组件中用props获取父组件传递来的参数:
      <script>
      export default {
          name: 'son',
          props: ['logo'],
      }
      </script>
      
  • 子组件-->父组件(通过$emit事件传递来向父组件传参)
    1. 子组件视图中绑定方法,在方法中用$emit方法遍历父组件中自定义的transfer事件,(transfer功能类似于一个中转),this.name将通过这个事件传递给父组件
      <template>
          <div class="daughter">
              <label>daughter:<input v-model="name" @change="setName" /></label>
          </div>
      </template>
      
      <script>
      export default {
          name: 'daughter',
          data() {
              return {
                  name: ''
              }
          },
          methods: {
              setName: function() {
                  this.$emit('transfer',this.name)
              }
          }
      }
      </script>
      
    2. 父组件中引入子组件,自定义一个事件transfer绑定一个方法,用此方法获取子组件传递的参数
      <template>
          <div class="parent">
              <daughter @transfer="getName"></daughter>
              <p>daughter获取到的name:{{name}}</p>
              <router-view />
          </div>
      </template>
      
      <script>
      import daughter from './daughter'
      export default {
          data() {
              return {
                  name: '', 
              }
          },
          methods: {
              getName(msg) {
                  this.name = msg;
              }
          },
          components: {
              daughter
          }
      }
      </script>
      
  • 兄弟组件之间的传参(通过vuex状态管理方法)
    1. 安装Vuexcnpm i vuex -S

    2. src中新建目录vuex,并新建一个store.js文件, 在store.js中引入VueVuex,只存入一个状态author

      import Vue from 'vue'
      import Vuex from 'vuex'
      
      Vue.use(Vuex)
      
      const store = new Vuex.Store({
        // 定义状态
        state: {
          author: 'Wise Wrong'
        }
      })
      export default store
      

      main.js全局引入vuexstore.js文件

      import Vue from 'vue'
      import App from './App'
      import router from './router'
      import Vuex from 'vuex'
      import store from './vuex/store'
      Vue.use(Vuex)
      Vue.config.productionTip = false
      new Vue({
        el: '#app',
        router,
        store,
        components: { App },
        template: '<App/>'
      })
      
    3. 通过2的全局引入之后,项目里的页面文件或组件文件就都可以使用了。使用时引入store文件,通过this.$store.getters.name直接访问;或者封装getters导出后通过mapGetters,mapMutations来调用全局状态数据和方法

  • 兄弟组件之间的传参(通过事件总线eventBus)

六、el-table中formatter过滤器:

vue3 不再支持filter过滤器

  • formatter属性:在视图中,在 Vue 表格中,可以在相应需要处理的<el-table-column>列中加上属性项:formatter=FunctionName。将该列数据与处理函数进行绑定。
    <el-table-column :formatter="regTypeFormatter" prop="regType" label="身份类型" min-width="100"/>
    
  • 定义过滤器filters:在script中设置好之后可以在视图中引用;

过滤器可以串联:{{ message | filterA | filterB }}

export default {
  components: { },
  filters: {
    formatStatus(status) {
      if (status === 2) {
        return "待确认"
      } else if (status === 3) {
        return "待发货"
      } else if (status === 4) {
        return "已驳回"
      } else if (status === 5) {
        return "已发货"
      } else {
        return "未知状态"
      }
    }
  },
  props: {
    takeId: {
      type: Number,
      default: null
    }
  },
  data() {
    return { }
}
}

七、vue中的ref$refs

ref 被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上; 如在普通的DOM元素上使用,引用指向的就是DOM元素; 如用在子组件上,引用就指向组件实例

关于ref注册时间,因ref本身是作为渲染结果被创建的,在初始渲染的时候你不能访问他们,他们还不存在。

$refs也不是响应式的,因此不能试图用她在模板中做数据绑定。要避免在模板和计算属性中使用$refs

八、Vuex状态管理

getters:可以让你从state中派生出一些新的状态。getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算(类似于计算属性)。

state:虽然statedata有很多相似之处,但state在使用的时候一般被挂载到子组件的computed计算属性上,这样有利于state的值发生改变的时候及时响应给子组件。

mapStatemapStatestate的辅助函数,返回state数据。

mapGetters 辅助函数仅仅是将getter 映射到局部计算属性

    import { mapGetters } from 'vuex'
    export default {
    computed: {
      // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
       ])
      }
    }
    // 如果你想将一个 getter 属性另取一个名字,使用对象形式:
    mapGetters({
      // 映射 `this.doneCount` 为 `store.getters.doneTodosCount`
      doneCount: 'doneTodosCount'
    })
    computed: {
      ...mapGetters(["elements"])
    },

dispatch:含有异步操作,例如向后台提交数据,写法 this.$store.dispatch('action方法名',值)

commit:同步操作,写法:this.$store.commit('mutations方法名',值)

handleLogin() {
  this.$refs.loginForm.validate(valid => {
    if (valid) {
      this.loading = true;
      this.$store.dispatch("LoginByUsername", this.loginForm).then(() => {
        this.loading = false;
        const company_params = '/'+this.$store.getters.company_params;
        this.$router.push(company_params + "/dashboard");
      }).catch(() => {
        this.loading = false;
      });
    } else {
      return false;
    }
  });
},