Vue 学习笔记


父 => 子 传值

父组件中定义属性 <com-a :aaa="parm"> ,子组件通过 props:['aaa'] 获取


子 => 父 传值

父组件中自定义事件 <com-a @aaa="parm"> ,子组件通过 methods:{this.$emit('aaa',要传的值)}向父元素传值


v-test / v-html

v-test:所有内容转换为字符串输出
v-html:如果有标签就按标签转换


组件中为什么 data(){return{}} 而不是 data:{}

防止修改 data 内容时由于引用传值导致误改了其他 template 组件


v-if / v-show

v-if 标签有 / 没有
v-show 通过 display:none 控制


其他

<template lang="jade"> 使用 jade 模板
<style lang="less"> 使用 less 语法


watch

属性监听

data(){
  abc:'',
}
watch:{
  abc:function(val,oldval){
    // 当 abc 发生变化时触发函数,可通过两个参数获取到变化前后的值
  }
}

计算属性有两种方法(视频第三章 5-7 节后半部分)

  • computed
  • 自定义方法,实时调用

插槽

  • <slot> :将要插入的内容放到子组件标签中,在子组件中使用 <slot></slot>
  • 可命名 :<p slot="head"></p>,对应子组件中<slot name="head"></slot>

缓存标签内的信息

  • <keep-alive></keep-alive>

组件的动态切换

<p :is="currentView"></p>
  data(){
    return{
      currentView:'com-a'
    }
}

通过对 currentView 动态切换实现组件切换,这里 com-a 是写好的组件


过渡效果

  • 通过 <transition name="aa"> 内置组件,组件可以命名,可以通过两种方式实现,需要给过渡的作用标签加上 v-show 或者 v-if
    • CSS 过渡
    • JS 过渡
  • CSS 过渡 官网有个图非常直观,对比官网例子
图示

整个过程可分为:
1.刚开始淡入
2.完全显示
3.完全消失
.fade-enter 刚要进入的瞬间 => 1
.fade-leave-to 完全离开的瞬间 => 3

.fade-enter-active {            // 进入的过程
  transition: all .5s ease;   
}
.fade-leave-active {            // 离开的过程
  transition: all .5s ease;
}
.fade-enter {                   // 刚进入的瞬间
  transform:translateX(200px);
  opacity: 0
}
.fade-leave-to {                // 离开终点的瞬间
  transform: translateX(200px);
  opacity: 0
}
  • 当使用 is 属性 + transition 实现组件切换的过渡效果时,<transition>有个默认的属性 mode="in-out" ,这样的效果是:新组件先进入,而旧组件后消失,这样会有个效果上的不和谐。改成 mode="out-in" 就好
  • 多个标签或者组件进行过渡切换时,如果标签名相同,比如两个<p>标签切换显示隐藏,并且标签上没有 key 属性时,切换效果会无效。这是由于 vue 最大化重用标签或组件,实际上是针对一个 <p> 标签进行操作,所以需要在两个 <p> 标签加上不同的 key 属性作为区分,避免重用
  • <transition><keep-alive> 共用时,需要 <transition> 在外

自定义指令

  • 局部自定义指令 - 写在某个组件中
  • 全局自定义指令 - 写在根节点实例化时 new Vue 时(main.js 中)
    <p v-color="'red'">自定义指令</p>    // 注意传的是字符串red,所以写的是 'red'(带引号)
    ...
    directives:{
      color:function(el,binding){
        el.style.color = binding.value
        }
      }
    
  • el :指令所绑定的元素,可以用来直接操作 DOM
  • binding:一个对象,包含namevalue等多个属性
  • 指令定义函数提供了几个钩子函数(见官网):
    • bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

插件

  • 安装方法
    • npm install vue-router --save--save 是安装插件后,让 package.json 中同步更新)
    • 在全局中引用 vue-router
      • main.js 中最上面 import VueRouter from 'vue-router'
      • main.js 中加入 Vue.use(VueRouter)

Vue - cli

  • npm install vue-cli -g 全局安装
  • vue init webpack 新建项目名 初始化项目
  • npm install 安装项目依赖
  • npm run devlocalhost 启动测试服务器
  • npm run build (部署)

Vue - router

  • 写在 <router-link> 中的是 声明式导航,另一种是写在
    JS 中的 编程式导航

  • this.$route.path // 全部的路径值

  • this.$route.params // 带 : 的部分
    console.log(this.$route.params) // Object {color: "xxxx", name: "xxx"}

    {
        path: '/apple/:color/ok/:name',
        name: 'apple',
        component: Apple
      }
    
  • 子路由的匹配方式

    • 如果配置中设置了 name 属性(也就是 命名路由),则也可以在 <router-link :to="{name:"xxx"}" tag="li"> 中通过 name 属性调用。其中 tag 属性可以将默认的 <a> 改为 <li>
    • 命名路由 / 命名视图
    // 命名路由
    <router-link :to="{name:'apple2'}"> 命名路由 </router-link>
    {
      path: '/apple',
      name: 'apple2',
      component: Apple,
      children:[
        {
          path:'applechild',
          component:applechild
        }]
    }
    
    // 命名视图
    <router-view name="viewA"></router-view>
    <router-view name="viewB"></router-view>
    
    // index.js 中
    path: '/apple',
    name: 'apple2',
    components: {
        viewA: Apple,
        viewB: Banana
    },
    
  • 可以在标签中通过类似 <p>{{$route.params.color}}</p> 语法调用
    此外,一旦添加了诸如 :color 这种参数, <router-link>to 属性值必须格式完全匹配 index.js 中的路径地址(如上例中,url 地址必须为
    /apple/param1/ok/param2),否则不会跳转到响应的组件,注意看 to 需不需要加 :

  • 正常跳转的时候会有 hash# ,通过在 index.js 中设置 mode: 'history',即可

    export default new Router({
      mode:'history',
      routes:[{
        ...
      }]
    })
    
  • 编程式导航

    • index.js 中通过 router.push({path:'xxx'}) 实现
    • 也可以配合 Vue-router 的钩子函数,比如 router.beforeEach() 可以实现跳转之前先执行一个判断之类的
  • 重定向

    • 当访问根目录时,自动跳转到 apple 路由
    {
      path: '/',
      redirect:'apple',       // 重定向
      name: 'Hello',
      component: Hello
    },
    
  • router-link-active


Vuex

Centralized State Management for Vue.js
  1. $ cnpm install vuex --save
  2. main.js (入口文件)中引入
// main.js
import Vuex from 'vuex'           //      1. 引入
Vue use (Vuex)                    //      2. 注册
let store = new Vuex.store({
                                  //      3. 配置
  mutations:{
      fn1(){
          ...
      },
      fn2(){
          ...
      },
  }
})
new Vue({
  el: '#app',
  router,                        
  store,                            //      4. 全局使用
  template: '<App/>',
  components: { App }
})

// 子组件中
this.$store.state                  // 5. 在子组件中调用 store 中的状态
this.$store.commit('fn1',传值)     // 6. 可以通过 commit 调用 store 中 mutations 内的各种方法,进而改变 store 中的参数
this.$store.commit('fn2',传值)
  • 关于 mutationsactions
    mutations 用来直接管理 state 的,因此 mutations同步 的(mutations 内的方法是一行一行执行)
    actions 用来调用 mutations 中的方法,是 异步 的(actions 中的某个方法在执行的过程中可以去请求个数据啥的,不耽误后面代码执行)
    // <template> 中通过 dispatch 调用 actions 中的方法
      plus(){
          this.$store.dispatch('increase',100)
      },
    
    // actions 中 通过 commit 调用 mutations 中的方法
      mutations:{
          increment (state,price){
              state.totalPrice += price
          },
          decrement (state,price){
              state.totalPrice -= price
          },
      },
      actions:{
          increase (context,price){
              context.commit('increment',price)
          }
      }
    

  • gettersstore 中的一个属性。可以通过 getters 获取到 state 中的某个状态,进行进一步的操作,比如: state 中有个数组,使用 getters 获取到这个数组,然后对数组进行过滤或者计算啥的
    let store = new Vuex.Store({
        state: {
            totalPrice:0
        },
        getters:{
            way(state){
                return state.totalPrice;
            }
    },
    
    // <template> 中调用
    this.$store.getters.xxx
    
  • modules:Talk is cheap
    // 定义
    const modulesA = {
      state:{...},
      mutations:{...},
      actions:{...},
      getters:{...},
    }
    const modulesB = {
      state:{...},
      mutations:{...},
      actions:{...},
      getters:{...},
    }
    // 配置
    let store = new Vuex.Store({
      modules:{
          a:modulesA,
          b:modulesB
      }
    })
    // 调用
    store.state.a       // moduleA's state
    store.state.b       // moduleB's state
    
  • 官方推荐使用 Vuex 项目的结构
    ├── index.html
    ├── main.js
    ├── api
    │   └── ... # 抽取出API请求
    ├── components
    │   ├── App.vue
    │   └── ...
    └── store
      ├── index.js          # 我们组装模块并导出 store 的地方
      ├── actions.js        # 根级别的 action
      ├── mutations.js      # 根级别的 mutation
      └── modules
          ├── cart.js       # 购物车模块
          └── products.js   # 产品模块
    

关于双向绑定

  • 先进行初始化的数据绑定,将实际的 DOM 节点劫持到
    documentFragment
  • 响应式数据绑定,主要是实现 input 输入内容时,data 跟着变化,需要做的就是通过 ES5defineProperty 进行数据的观察和修改
  • 实现 data 改变同步页面中的数据更新,观察者模式,可以是多个观察者对数据进行监听,当数据改变后,会触发一个更新的函数,进而实现页面的更新
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容