Fork me on GitHub

Vue 学习文档

Vue 学习文档

vue 起步

  1. 引包
  2. 启动 new Vue(options)
  3. options:
  • el 目的地(可以用类名、标签名等,也可以直接用mod元素)
    • #elementId
    • .elementClass
    • div
    • document.getElementById('elementId')
  • template 内容
  • data 数据

vue 基础语法

vue 指令

  • v-if 是否插入元素
  • v-show 是否隐藏元素
  • v-bind 给元素属性赋值,单向数据绑定
    • 简写::{属性名}=
  • v-model 在表单控件或者组件上创建双向绑定
  • v-on 绑定事件
    • 简写: @{事件名}=
    • 传参 直接在方法名后追加(参数)
    • 同时获取参数和event对象 v-on:click="warn('参数', $event)"
  • v-for 遍历
    • 循环数组 (item, index)

    • 循环对象 (val, key, index)

      <div v-for="(item, index) in items"></div>
      <div v-for="(val, key) in object"></div>
      <div v-for="(val, key, index) in object"></div>
      

vue 组件化

  • 使用步骤:

    • 编写子组件
    • 声明子组件
    • 使用子组件
  • 父组件向子组件传递数据

    • 父组件用v-bind传递,子组件必须props里先声明

    • props可以设置默认值

    • props可以指定数据类型(String/Number/Boolean/Array/Object/Date/Symbol/Function)

      const MyHeader = {
          template: `<h1>我是头部</h1>`
      }
      const MyBody = {
          template: `<h1>我是中部 {{index}}</h1>`,
          //props: ['index'],
          props: {
          items: {  // 必须提供字段
              type: String, //指定类型
              required: true
          },
          index: {   // 可选字段,有默认值
              type: Number,
              default: 3
          },
          // 带有默认值的对象
          propE: {
              type: Object,
              // 对象或数组默认值必须从一个工厂函数获取
              default: function () {
              return { message: 'hello' }
              }
          },
          // 自定义验证函数
          propF: {
              validator: function (value) {
              // 这个值必须匹配下列字符串中的一个
              return ['success', 'warning', 'danger'].indexOf(value) !== -1
              }
          }
          }
      }
      let app = new Vue({
          el: '#demo1',
          components: {
              'my-header': MyHeader,
              'my-body': MyBody,
              'my-footer': MyFooter
          },
          template: `
              <div>
                  <my-header/>
                  <my-body :index="tip"/>
              </div>
          `,
          data: {
              tip: 1
          }
      })
      
  • 注册全局组件

    • Vue.component('组件名',组件对象)
  • 全局组件不带 's'

过滤器-filter

  • 全局过滤器:

    Vue.filter('my-filter', function (value) {
    // 返回处理后的值
    })
    
  • 组件内的过滤器 filters:{ '过滤器名','过滤方式fn' }

    • fn中的参数1是传递的数据,允许追加额外的参数
    • return是返回显示的内容
    • 使用:{{ myText | 过滤器名 }}
    • 场景:处理后台返回数据

监控-watch

  • watch和v-model的区别:

    • v-model仅仅是数据的同步,watch可以数据和行为挂钩
  • 参数:(newVal,oldVal)

    watch({'myText': function (newVal, oldVal) {
    // 做点什么
    }})
    
  • 无法监视复杂数据,watch监控的是引用地址

  • 深度监视的方法:

    watch({'myText': {
        deep: true,
        handler: function (newVal, oldVal) {
        // 旧值将与新值相同
        }
    }})
    

计算-computed

  • 凡是函数内部有this.相关属性,改变都会触发当前函数

  • 计算属性默认只有 getter

    computed: {
        // 计算属性的 getter
        fullName: function () {
        // `this` 指向 vm 实例
        return this.firstName + ' ' + this.lastName
        }
    }
    
  • 也可以提供一个 setter

    computed: {
        fullName : {
            //this.firstName改变或this.lastName改变触发get方法
            //this.fullName改变时执行set方法
    
            get: function () {
                return this.firstName + ' ' + this.lastName
            },
            set: function (newValue) {
                var names = newValue.split(' ');
                this.firstName: names[0];
                this.lastName: names[names.length - 1];
            }
        }
    }
    

具名插槽-slot

  • 插槽可以让组件像原生标签一样使用

  • 使用方法:定义的组件中包含 <slot>

    组件:
    <a
    v-bind:href="url"
    class="nav-link"
    >
    <slot></slot>
    </a>
    使用:
    <navigation-link url="/profile">
    Your Profile
    </navigation-link>
    
  • 插槽内可以包含任何模板代码,包括 HTML

  • <slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽

  • 可以在组件模板里的 <slot> 标签内部指定默认的内容

组件生命周期

  • beforeCreate 组件创建前
  • created 组件创建后
    • 可以操作data中的数据
    • 对应父组件 v-if=true 时触发
  • beforeMount 组件装载前
  • mounted 组件装载后
  • beforeUpdate 组件更新前
    • 可以获取原dom
  • updated 组件更新后
    • 数据发生改变触发
    • 可以获取新dom
  • beforeDestroy 组件销毁前
  • destroyed 组件销毁后
    • 对应父组件 v-if=false 时触发

注意:使用v-if频繁触发组件创建与销毁不合理,应该使用 <keep-alive> 包裹组件

  • activated <keep-alive> 包裹的组件激活
  • deactivated <keep-alive> 包裹的组件停用

获取DOM元素/组件对象-ref

  1. 在组建的DOM部分,任意的标签中写上 ref="{自定义元素名}"

  2. 通过组件对象 this.$refs.{自定义元素名}获取到元素

  3. 可以在mounted中操作DOM数据

  4. 在子组件标签中写入 ref="{自定义组件名}",获取到的就是组件对象

  5. Vue中DOM更新是异步的,异步导致DOM未渲染,无法操作DOM元素的解决办法

    this.$nextTick(function(){
      //执行
    })
    

vue 插件

vue-router的使用

  • 路由原理:

    • 添加hashChange事件,通过location.hash控制innerHTML
  • vue-router使用步骤:

    1. 引入vue-router.js
    2. 安装插件
    3. 创建一个路由对象
    4. 配置路由对象
    5. 将配置好的路由对象关联到vue实例中
    6. 制定路由改变局部的位置
    Vue.use(VueRouter);
    var router = new VueRouter({
        routes: [
            { name:'login', path: '/login',component: Login },
            { name:'register', path: '/register',component: Register }
        ]
    })
    //也可以router.addRoutes([{},{}])
    var app = {
        template:`<div>
            <router-link to="/login">登录</router-link>
            <router-link :to="{name:'register'}">注册</router-link>
            <router-view></router-view>
        </div>`
    };
    new Vue({
        el: "#app",
        router:router,
        components:{
            app:App
        },
        template: '<app/>'
    })
    
  • url传参数

    • 查询字符串
      1. 配置:在router-link标签中注册参数内容 <router-link :to="{name:'register',query:{id:1}}">注册</router-link>
      2. 规则:{ name:'register', path: '/register',component: Register }
      3. 生成:<a href="/register?id=1">
      4. 获取: 子组件中使用this.$route.query获取参数对象
    • path方式
      1. 配置::to="{name:'register',params:{id:1}}"
      2. 规则: { name:'register', path: '/register/:id',component: Register }
      3. 生成: <a href="/register/1">
      4. 获取: this.$route.params
  • $router Vs. $route

    • $router VueRouter路由对象
    • $route 路由信息对象
  • 嵌套路由

    • router-view套router-view,路由children路由

      
      const Login = {
          template: `<div>
              我是登录页
              <router-link :to="{name:'login.woman'}">女性登录页</router-link>
              <router-view></router-view>
          </div>`,
      };
      
      var router = new VueRouter({
          routes: [{
              name: 'login',
              path: '/login',
              component: Login,
              children: [{
                  name: 'login.woman',
                  path: 'woman',
                  component: Woman
              }]},
              {name: 'register', path: '/register', component: MyHeader}
          ]
      })
      
  • 权限控制

    • router.beforeEach((to,from,next) => {})
      • 每次路由匹配后,渲染组件前
      • to 跳转后路由信息对象
      • from 跳转前路由信息对象
      • next 放行 next()
      • next 取消用户导航next(false)
      • next方法里添加参数可以重定向next( { name:'login' } )
    • 路由meta元数据 > 对于路由规则是否需要验证权限的配置
      • 路由对象中和name属性同级 {meta:{isChecked:true}}
  • 路由懒加载

    • 优化流量,按需请求

axios

  • axios挂载到vue对象上:

    • Vue.prototype.$axios = axios;
  • 合并请求

    axios.all([getUerAccount(),getUserPermissions()])
        .then(axios.spread(function(acc,pers){
            //两个请求现在都完成
        }));
    
  • 取消请求

    const CancelToken = axios.CancelToken;
    const source = CancelToken.source(); // 创建标识请求的源对象
    
    this.source = source; // 讲对象存储到组件
    cancelToken: source.token, // 请求的options属性
    this.source.cancel(); // 取消到之前的那个请求
    
    //前端的断电续传,及时获取当前上传的文件大小,储存起来
    var file = <input type="file"/> .files[0].slice(文件开始部分,文件结尾部分)
    new FormData().append('file',file);
    
    // 后台就是接受多次文件,都往上传文件上追加
    
  • 拦截器

    • 请求拦截器:在发起请求之前,做的事

    • 响应拦截器:在响应回来以后,做的事

      axios.interceptors.request.use(function(config){
          //在请求发送之前做一些事
          return config;
      },function(error){
          //当出现请求错误是做一些事
          return Promise.reject(error);
      });
      
      axios.interceptors.response.use(function(response){
          //对返回的数据进行一些处理
          return response;
      },function(error){
          //对返回的错误进行一些处理
          return Promise.reject(error);
      });
      
  • post发送数据为"name='jack'"时,数据类型为formData形式

  • 参数

    • this.$axios.defaults 修改公共配置
    • transformRequest 加工请求体数据
    • transformResponse 加工返回数据
    • withCredentials:false 跨域请求默认不带cookie
    • 携带token
      • xsrfCookieName:'XSRF-TOKEN',//默认值
      • xrsfHeadername:'X-XSRF-TOKEN',//默认值

webpack

  • 源码分析
    1. 把所有模块的代码放入到函数中,用一个数组保存起来
    2. 根据require时传入的数组索引,能知道需要哪一段代码
    3. 从数组中,根据索引去除包含我们代码的函数
    4. 执行该函数,传入一个对象module.exports
    5. 我们的代码,按照约定,正好是用module.exports='xxx'进行赋值
    6. 调用函数结束后,module.exports从原来的空对象就有值了
    7. 最终return module.exports所为require函数的返回值

Vuex

  • 使用步骤
    1. 引入并安装vuex插件
    2. 创建store对象const store = new Vuex.Store()
    3. 配置store中的数据/存/取
    4. 将vuex关联到vue实例中
  • 数据获取
  • 数据修改
    • this.$store.commit()
    • 禁止使用this.$store.state.xxx=直接修改

其他

SPA 单页面应用程序

  • vue-router默认使用hash模式,可以使用history模式去除#
  • 在history模式下,可以scroll导航后滚动
  • history模式实现其实基于服务器每次返回index.html而客户端根据location.pathname来做渲染

SEO 搜索引擎优化

  • SPA下SEO必然较差
  • 使用与渲染,固定的页面作为服务器响应的结果

常用点

父组件中调用子组件的方法:

  • 先给子组件定义属性 ref="xxx"
  • 生命周期中用this.$refs.xxx获取此子组件对象
  • 由于组件是异步的,如果在created中调用会返回undefined,解决办法是this.$nextTick(function(){ //执行 })

Element Ui组件Events事件使用方法

  • 组件对象methods中定义回调方法
  • 组件标签中引入@close="handleClose"

eventbus使用

  • bus.$on('event', msg => {// 执行操作})注册监听事件
  • bus.$emit('event', msg)触发监听操作

antd Form组件---mapPropsToFields

  • 子组件的mapPropsToFields可以触发父组件change事件
  • mapPropsToFields 里面返回的表单域数据必须使用 this.$form.createFormField 包装。
  • this.form.setFieldsValue用于在表单生成以后设置值

自定义组件内部触发组件change事件

  • this.$emit('change', arguments);
posted @ 2019-05-28 11:19  gaiyb  阅读(223)  评论(0编辑  收藏  举报