vue常见指令、路由、导航守卫、生命周期、vuex整理

vue 笔记

vue 简介

  • Vue.js 是目前最火的一个前端框架,React 是最流行的一个前端框架(React 除了开发网站,还可以开发手机 App,Vue 语法也是可以用于进行手机 App 开发的,需要借助才 Weex)
  • Vue.js 是前端的主流框架之一,和 Angular.js、React.j3 一起,并称为前端三大主流框架;
  • Vue.js 是一套构建用户界而的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue 有配套的第三方类库,可以整合起来做大型项目的开发)
  • 在 Vue 中,一个核心的概念,就是让用户不再操作 DOM 元素,Vue(React) 提供了虚拟 DOM,对比虚拟 DOM 与真实 DOM 不同之处,每次对不同部分进行渲染,渲染效率更高。

提高开发效率的发展历程:

  • 原生 JS->Jquery 之类的类库->前端模板引擎->Angular.js/ Vue.js(能够帮助我们减少不必要的 DOM 操作;提高渲染效率;双向数据绑定的概念)

框架和库的区别

  • 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目
    • 如node 中的 express;
  • 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
    1. 从 Jquery 切换到 Zepto
    2. 从 EJS 切换到 art-template

vue 和 angular 的区别

  • vue——简单、易学
    • 指令以 v-xxx
    • 一片 html 代码配合上 json,在 new 出来 vue 实例
    • 个人维护项目
    • 适合: 移动端项目,小巧
    • vue 的发展势头很猛,github 上 start 数量已经超越 angular
  • angular——上手难
    • 指令以 ng-xxx
    • 所有属性和方法都挂到$scope 身上
    • angular 由 google 维护
    • 合适: pc 端项目

安装使用

  1. 独立版本
    • 直接下载并用 script 标签引入,Vue 会被注册为一个全局变量。
  2. 脚手架 vue-cli
    • 全局安装:npm install -g vue-cli (或 npm i -g vue-cli
    • 创建项目:
      • 选择项目所在的位置,通过命令行进入该目录(或者直接在该目录,右键,打开命令行)。
      • 使用脚手架安装项目:vue init webpack demo 项目是基于 webpack 的
        • Project name(工程名):回车
        • Project description(工程介绍):回车
        • Author:作者名
        • Vue build(是否安装编译器):回车
        • Install vue-router(是否安装 Vue 路由):y
        • Use EsLint to lint your code(是否使用 EsLint 检查 js 代码):n
        • Set up unit tests(安装单元测试工典):n
        • Set up e2e tests with Nightwatch(是否安装端到端测试一关):n
        • Should we run npm install for you after the project has been created?(recommended):
          No, I will handle that myself 回车。
    • 启动项目
      • 进入项目:cd demo 或 vscode 打开
      • 安装项目所需要的依赖:npm install
      • 启动项目:npm run dev 启动成功,浏览器打开
    • 配置目录:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGJaHIAh-1574426063682)(./assets/vue-content.png)]

Vue 的基本代码

<html>
  <body>
    
    
    <div id="app">
      
      <p v-lock>{{msg}}p>
    div>
    <script src="./js/vue2.5.17.js">script>
    <script>
      // 创建一个Vue的实例
      // 当我们导入包之后,在浏览器的内存中,就多了一个Vue构造函数
      // 注意:我们new出来的这个vm对象,就是我们MVVM中VM调度者
      var vm = new Vue({
        el: "#app", //表示,当前我们new出来的这个Vue实例,要控制页面上的哪个区域
        data: {
          //这里的data就是MVVM中的M,专门用来保存每个页面的数据的
          //data属性中,存放的是el中要用到的数据
          msg: "Vue" //通过Vue提供的指令,很方便的就能把数据渲染到页面上,不用在手动操作DOM元素了【前端的Vue、Angular之类的框架不提倡手动操作DOM元素了】
        }
      });
    script>
  body>
html>

模板语法

  • Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
    • Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。
    • 在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时,Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。

Vue 指令

  • v-text 指令:绑定 html 元素的文本内容,会覆盖元素中原本的内容,不会解析

  • v-html 指令:绑定 html 元素的 html 标签,会覆盖元素中原本的内容,会解析

  • v-model 指令:实现数据的双向绑定

  • v-once 指令:仅渲染一次

  • v-show 指令:显示隐藏

  • v-cloak 指令:当模板未编译完成时,结合 display:none 使用,解决插值表达式闪烁问题。只替换自己的占位符,不会把整个元素的内容清空

  • v-bind 指令:v-bind:属性名称=“值” 绑定 html 元素的属性 v-bind 可省

  • v-on 指令:接收方法处理事件 语法 v-on:事件=“函数” 简写 @事件=“函数”

    • 阻止冒泡 @事件.stop
    • 阻止默认行为/事件 @事件.prevent
    • 键盘事件@keydown, @keyup
      • 回车 @keyup.13 @keyup.enter
      • 上下左右
        • @keyup.left/@keydown.left
        • @keyup.right/@keydown.right
        • @keyup.up/@keydown.up
        • @keyup.down/@keydown.down
  • 渲染指令

    1. 条件渲染 v-if v-else-if v-else
    2. 循环渲染 v-for
      • 迭代对象:参数 1 属性值,参数 2 属性名称,参数 3 索引
    
    <head>
      <style>
        [v-cloak] {
          display: none;
        }
      style>
    head>
    <body>
      <div id="app" v-cloak>
        <p>您的成绩:{{grade}},{{ grade >= 60?'合格':'不合格'}}p>
        <p v-text="grade">p>
        <p v-text="msg">p>
        <p v-html="msg">p>
        <input type="text" v-model="name" />
        <h2>hello{{name}}h2>
        <p v-once>{{name}}p>
        <p>
          您的成绩等级:
          <span v-if="grade>=80">优秀span>
          <span v-else-if="grade>=70">良好span>
          <span v-else-if="grade>=60">合格span>
          <span v-else>合格span>
        p>
        <ul>
          <li v-for="item in courseList">{{item}}li>
        ul>
        <ul>
          <li v-for="(item,index) in courseList">{{item}}-{{index}}li>
        ul>
        <p v-for="(value,key,index) in student">{{value}}-{{key}}-{{index}}p>
        <img v-bind:src="imgUrl" alt="" />
        <img :src="imgUrl" alt="" />
        
        
        
        <a href="url" :style="{textDecoration:'none'}">baidua>
      div>
    body>
    

    Vue 自定义指令

    • 除了核心功能默认内置指令(v-model 和 v-show),Vue也允许自定义指令。

    • 普通 DOM 元素进行底层操作要用到自定义指令

    • 建议在给指令的命名采用小驼峰式的命名方式,比如 changeBackgroundColor,在使用的时候,采用烤串式写法 v-change-background-color

    • 一个指令定义对象可以提供如下几个钩子函数:

      • bind:只调用一次,指令第一次绑定到元素时调用。
      • inserted:被绑定元素插入 DOM 中时调用
      • update:所在组件的 VNode 更新时调用 ,但是可能发生在其子 VNode 更新之前。
      • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
      • unbind:只调用一次,指令与元素解绑时调用。
    • 指令钩子函数会被传入以下参数:

      • el:指令所绑定的元素,可以用来直接操作 DOM 。
      • binding:一个对象,包含以下属性:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值。
      • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
      • expression:字符串形式的指令表达式。
      • arg:传给指令的参数,可选。
      • modifiers:一个包含修饰符的对象。
      • vnode:Vue 编译生成的虚拟节点。
      • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
      new Vue({
        el: "#app",
        data: { bgcolor: "orange" },
        methods: {},
        filters: {},
        // 局部注册自定义指令(对指令绑定的元素进行DOM操作),添加directives
        directives: {
          changeBackgroundColor: {
            bind(el, binding) {
              console.log("el:", el, ",binding:", binding);
              el.style.backgroundColor = binding.value;
            }
          },
          focus: {
            inserted(el) {
              // 触发元素的focus事件,让其获得焦点
              el.focus();
            }
          }
        }
      });
      

    Vue 与后端的交互(axios 及跨域)

    • 项目开发前面:前后端是各自开发:前端模拟假数据开发页面;后端开发 api
    • 项目后面
      • 后端提供数据接口,前端使用 ajax/axios 技术进行解析从而渲染数据到页面上
      • 后端提供数据的格式一般是 json,如果不是,前端拿到数据后,转换为 json 格式,然后使用 ajax/axios 进行解析从而渲染页面

    Vue 过滤器

    • 过滤器用来格式化数据,过滤器能够用在表达式和指令中,使用一个管道字符(|)添加到表达式和指令中。{{msg | filter}}
    // 局部注册过滤器:在Vue实例中添加filters选项
    new Vue({
      el: "#app",
      data: {
        price: 17,
        ammount: 4,
        time: new Date()
      },
      methods: {},
      filters: {
        // 过滤器函数:参数1-要格式化的数据,参数2-过滤器参数,必须有返回值(格式化之后的数据)
        currency: function(value, op = "$") {
          return op + value.toFixed(2);
        },
        date: function(value) {
          // 常用日期过滤器  日期格式:yyyy-MM-dd HH:mm:ss
          let y = value.getFullYear();
          let m = value.getMonth() + 1;
          let d = value.getDate();
          let h = value.getHours();
          let mi = value.getMinutes();
          let s = value.getSeconds();
          return `${y}-${m < 10 ? "0" + m : m}-${d < 10 ? "0" + d : d} ${
            h < 10 ? "0" + h : h
          }:${mi < 10 ? "0" + mi : mi}:${s < 10 ? "0" + s : s}`;
        },
        // 对数值进行格式化,保留小数位(默认3位)10,000.000
        number: function(value, n = 3) {
          return value.toFixed(n);
        }
        // TODO filter过滤器,orderBy
      }
    });
    

Vue 生命周期

vue常见指令、路由、导航守卫、生命周期、vuex整理_第1张图片

Vue 组件

  • 组件中的数据共有三种形式:data、props、computed

  • 注册组件(注意:html 中不能使用单标记)

    • 全局注册
      // (1)注册全局组件,所有Vue实例中可以直接引用此组件
      /*
      参数1:组件名称,命名以大驼峰或-连接(小写单词)
      参数2:组件选项,template,data等
      例:MyComponent  my-component
      */
      Vue.component("my-compoent", {
        template: "
      Welcome to Vue!
      "
      });
      <div id="app">
        <my-compoent>my-compoent>
      div>
      
    • 局部注册
      // (2)注册局部组件,仅当前Vue实例可用
      const My = {
        template: "

      {{msg}}

      "
      , // data必须是函数 data() { //一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝 return { msg: "Hello Vue!" }; } }; // 建议将组件封装在一个独立的.js或.vue文件里面 new Vue({ el: "#app", data: {}, // 在Vue实例中添加componments选项来注册局部组件 components: { My // My:My } });
      <div id="app">
        <My>My>
      div>
      
    • 组件封装

      • 将其封装至单独的.vue 文件中放在 components 文件夹下

      • 单独的组件.vue 文件结构如下:

        <template>
        </template>
        
        <style scoped>
        /* scoped局部作用域,只在当前vue文件中生效 */
        </style>
        
        <script>
          export default {//默认导出vue文件,其中为vue实例的选项
            //el不要加,自动挂载到template上
            //data要写成函数形式
            data(){
              return{
              }
            }
          }
        </script>
        
    • 组件生命周期

      • main beforeCreate
      • main created
      • main beforeMount
      • App beforeCreate
      • App created
      • App beforeMount
      • App mounted
      • main mounted
      • App beforeUpdate
      • App updated
      • App beforeDestroy
      • Hello World destroyed
      • App destroyed
    • 父子组件间的通信 props down, events up

      • 父组件通过 props 向下传递数据给子组件

        • 父组件在引用子组件时,通过 v-bind:把需要传递给子组件的数据,传递到子组件内部,供子组件使用
        • 把父组件传递过来的数据在 props 数组中定义一下
          1. 组件中的所有 props 中的数据,都是通过父组件传递给子组件的
          2. props 中的数据都是只读的,无法重新赋值
        • 在子组件中使用 props 数组中定义好的数据
    • 子组件向父组件传值(通过事件形式)

      • 父组件使用事件绑定机制 v-on(@)定义事件属性传递给子组件
      • 在子组件中定义一个方法,在方法中,利用 $emit触发 组件传递过来的方法,挂载在当前实例上的事件,还可以传递参数
      • 在子组件中调用方法,触发父组件传递过来的方法
      //父组件App.vue
        <template>
          <div id="app">
            <img src="./assets/logo.png">
            <!-- 通过自定义属性,将值向下传递给子组件 -->
            <HelloWorld :number="count" @updCount="update"/>
            <button @click="update">App中更新</button>
          </div>
        </template>
      
        <script>
        import HelloWorld from './components/HelloWorld'
        export default {
          name: 'App',
          components: {
            HelloWorld
          },
          data(){
            return {
              count: 1
            }
          },
          methods:{
            update(a,b,c){
              console.log(a,b,c);
              this.count+=a;
            }
          }
        }
        </script>
        <style>
        </style>
      
      //子组件 HelloWorld.vue
      <template>
        <div class="hello">
          <p>计数器:{{number}}</p>
          <button @click="updateProps">子组件更新数据</button>
        </div>
      </template>
      <script>
      export default {
        name: 'HelloWorld',
        data () {
          return {
          }
        },
        props: ['number'],
        methods:{
          updateProps(){
            // props中的数据是只读的
            // this.number++;//不要直接更改props数据
      
            // Events Up触发父组件的事件,让父组件去更新
            // this.$emit('updCount');
            this.$emit('updCount',2,3,4);
          }
        }
      }
      </script>
      <style scoped>
      </style>
      

Vue 路由

路由的基本配置

  • 区分:
    • 当前路由对象:this.\$route
    • 路由管理器对象:this.\$router
    1. 安装 vue-router npm i vue-router --save
    2. 在 router 中 index.js 配置路由
      • 引入 vue 的路由管理器,自定义组件并引入路由组件
      • 安装 vue-router 路由的功能
      • 创建一个路由管理器对象并进行路由配置
      //引入 vue 的路由管理器
      import VueRouter from "vue-router";
      // 引入路由组件
      import Login from "@/components/Login";
      import Registe from "@/components/Registe";
      // 安装路由的功能
      Vue.use(VueRouter);
      // 创建一个路由管理器对象
      const router = new VueRouter({
        // 添加配置参数routes
        routes: [
          // path: 路由标记(路径),component: 路由标记对应的组件
          { path: "/log", component: Login },
          { path: "/reg", component: Registe },
          // 根路由
          { path: "/", redirect: "/log" }
        ]
      });
      export default router;
      
    3. 在 App.vue 中设置路由导航和路由出口,路由导航会渲染成 a 标签,配置好路由的路由组件会渲染到路由出口
      <!-- 路由导航:会渲染成a标签  -->
      <router-link to="/log">登录</router-link>
      <router-link to="/reg">注册</router-link>
      <!-- 路由出口:路由匹配到的组件会渲染在这里 -->
      <router-view></router-view>
    

带参数路由及路由嵌套

  • 带参路由

    • 一个"路径参数"使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。
    //router下index.js文件配置路由
    import Vue from 'vue'
    import Router from 'vue-router'
    import PhonesList from '@/pages/PhonesList'
    import Detail from '@/pages/Detail'
    Vue.use(Router)
    export default new Router({
      routes: [
        {
          path: '/',
          name: 'PhonesList',
          component: PhonesList
        },
        {
          path: '/detail/:id', //路由带参数,在路由标记后面添加 /:参数名称
          component: Detail
        }
      ]
    })
    //PhonesList.vue传递参数
    <template>
      <div>
        <ul>
          <li v-for="item in phones" :key="item.age">
            <h3><router-link :to="`/detail/${item.id}`">{{item.name}}</router-link></h3>
            <p>{{item.snippet}}</p>
          </li>
        </ul>
      </div>
    </template>
    <script>
      export default {
          data(){return {phones: []}},
          created(){
              // 请求所有的手机列表数据
              this.$axios.get('/static/data/phones.json').then(resp => {
                  this.phones = resp.data;
              });
          }
      }
    </script>
    <style scoped>
    </style>
    //Detail.vue 接收参数
    <template>
      <div>
          <h4>{{phone.name}}</h4>
          <p>{{phone.description}}</p>
          <router-link to="/">返回首页</router-link>
      </div>
    </template>
    <script>
      export default {
        data(){return {phone: {}}},
        beforeMount(){
          // 所有的组件中都可以访问路由管理器this.$router(VueRouter对象),当前路由this.$route
          // 当前手机的id参数
          let id = this.$route.params.id;
          this.$axios.get(`/static/data/${id}.json`).then(resp => {
              this.phone = resp.data
          })
        }
      }
    </script>
    <style scoped>
    </style>
    
  • 路由嵌套

    • 要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置
    //router下index.js配置路由
    import Vue from 'vue'
    import Router from 'vue-router'
    import Nav from '@/components/Nav'
    import TopicList from '@/components/TopicList'
    Vue.use(Router)
    export default new Router({
      routes: [
        /*
          重定向也通过 routes 配置
          { path: '/a', redirect: '/b’ } //从 /a 重定向到 /b
         */
        {
          path:'/nav',
          component: Nav,
          // 配置子路由
          children:[
            {
              // path:'/nav/TopicList/:tab',//访问的路由标记
              path:'TopicList/:tab',//访问的路由标记/nav/TopicList
              component: TopicList
            },
            // 默认子路由
            {
              path:'',
              redirect:'TopicList/all'
            }
          ]
        }
      ]
    })
    //App.vue
    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <router-link to="/nav">导航</router-link>
        <router-view/>
      </div>
    </template>
    //Nav.vue外层
    <template>
      <div>
          <ul>
              <li><router-link to="/nav/TopicList/all">全部</router-link></li>
              <li><router-link to="/nav/TopicList/good">精华</router-link></li>
              <li><router-link to="/nav/TopicList/ask">问答</router-link></li>
          </ul>
          <router-view></router-view>
      </div>
    </template>
    //TopicList.vue被嵌套的组件
    <template>
      <div>
        <h2>{{tit}}</h2>
      </div>
    </template>
    <script>
      export default {
        data(){return {tit: ""};},
        created() {console.log("TopicList created");},
        watch: {
          $route: { // 监听当前路由的变化
            handler: function() {this.tit = this.$route.params.tab;
              // 执行异步任务,比如请求后端接口中的数据
            },immediate:true}}
      };
    </script>
    <style scoped>ul{list-style: none;}</style>
    

导航守卫

  • 导航守卫主要用来通过跳转或取消的方式守卫导航
    • 全局守卫:是指路由实例上直接操作的钩子函数,特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数
      • beforeEach(to,from,next)
        • 在路由跳转前触发,用于登录验证
      • beforeResolve(to,from,next)
        • 在导航被确认之前,所有组件内守卫和异步路由组件被解析之后(beforeEach和beforeRouteEnter 之后,afterEach之前)调用。
      • afterEach(to,from)
        • 在路由跳转完成后触发,beforeEach和beforeResolve之后,beforeRouteEnter(组件内守卫)之前。这些钩子不会接受next函数也不会改变导航本身
    • 路由守卫: 是指在单个路由配置的时候也可以设置的钩子函数
      • beforeEnter(to,from, next)和beforeEach完全相同,如果两个都设置了,beforeEnter则在beforeEach之后紧随执行。在路由配置上直接定义beforeEnter守卫
    • 组件守卫:是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。
      • beforeRouteEnter(to,from, next)
      • beforeRouteUpdadte(to,from, next)
      • beforeRouteLeave(to,from, next)
      export default{
        data(){},
        beforeRouteEnter (to, from, next) {
          // 在渲染该组件的对应路由被 confirm 前调用
          // 不能获取组件实例 `this`
          // 因为当守卫执行前,组件实例还没被创建
        },
        beforeRouteUpdate (to, from, next) {
          // 在当前路由改变,但是该组件被复用时调用
          // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1和/foo/2 之间跳转的时候,
          // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
          // 可以访问组件实例 `this`
        },
        beforeRouteLeave (to, from, next) {
          // 导航离开该组件的对应路由时调用
          // 可以访问组件实例 `this`
        }
      }
      
  • 路由守卫回调参数
    • to:即将要进入的目标 路由对象
    • from :当前导航正要离开的路由
    • next: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数
    • next() - 通过
    • next(false) - 取消路由导航,停留在from
    • next(’/xx’) - 跳转到指定的路由
  //router.vue下index.js
  import Vue from 'vue'
  import Router from 'vue-router'
  import HelloWorld from '@/components/HelloWorld'
  import Login from '@/components/Login'
  import New from '@/components/New'
  import Cookies from 'js-cookie'
  Vue.use(Router)
  const router =  new Router({
    routes: [
      {
        path: '/',
        name: 'HelloWorld',
        component: HelloWorld
      },
      {
        path: '/new',
        name: 'New',
        component: New,
        // 添加路由元信息
        meta:{
          requireLogin:true
        }
      },
      {
        path: '/log',
        name: 'Login',
        component:Login,
         meta:{
          requireLogin:false
        }
      }
    ]
  })
  router.beforeEach((to, from, next) => {
    console.log('当前导航正要离开的路由',from,'即将要进入的目标',to);
    if(to.meta.requireLogin){/
      let username=Cookies.get('username');
      if(username){
        next();
      }else{
        alert('请先登录');
        next('/log');
      }
    }else{
      next();
    }
  })
  router.afterEach((to, from) => {
    console.log('afterEach',to);
  })
  export default router;
  //首页Helloworld.vue
  <template>
    <div class="hello">
      <h1>{{ msg }}</h1>
    </div>
  </template>
  <script>
    export default {
      name: 'HelloWorld',
      data(){return {msg: '欢迎来到博客园'}}
    }
  </script>
  <style scoped>
  </style>
  //tab切换页面App.vue
  <template>
  <div id="app">
   <ul>
      <li><router-link to="/">首页</router-link></li>
      <li><router-link to="/New">新随笔</router-link></li>
    </ul>
    <!-- 渲染位置 -->
    <router-view/>
  </div>
</template>
<script>
  export default {name: "App"};
</script>
<style>
</style>
//Login.vue主要代码登录页
<template>
  <div>
    <form>
      <input type="text" placeholder="账号" v-model="account" />
      <input type="password" placeholder="密码" v-model="password" />
      <input type="button" value="登录" @click="login" />
    form>
  div>
template>
<script>
import Cookies from "js-cookie";
export default {
  data() {
    return {
      account: "",
      password: ""
    };
  },
  methods: {
    login() {
      // 在cookie中保存登录的用户信息
      console.log("登录成功");
      Cookies.set("username", this.account);
      // 路由跳转
      this.$router.push("/New");
    }
  }
};
</script>

vuex 原理

  • Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更改 State 中的数据时,必须通过 Mutation 进行,Mutation 同时提供了订阅者模式供外部插件调用获取 State 数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走 Action,但 Action 也是无法直接修改 State 的,还是需要通过 Mutation 来修改 State 的数据。最后,根据 State 的变化,渲染到视图上。

vuex状态管理模式

  • Vuex是vue应用的状态管理器,管理Vue所有组件状态。
  • 通过vuex提供的store进行管理我们的数据,而vue只负责UI渲染的问题;数据的状态变更,由vuex来处理。
  • 应用场景:大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。- 为什么要应用vuex?
    • 把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。
  • 安装vuex: npm install vuex --save(生产依赖)
  • 引入及使用
    1. 新建store文件夹,在main.js中引入注册
import store from './store'
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '',
  // 注册store,在Vue组件内部通过this.$store来访问
  store,//store:store
  })
  1. 在store文件夹下index.js文件中安装Vuex并创建Store对象
import Vuex from 'vuex'
// 安装Vuex,在Vue实例中才能使用Vuex的功能
Vue.use(Vuex)
// Vuex中的核心是Store(仓库,存储的是组建的公共状态)
// 创建Store对象
const store=new Vuex.Store({
/*  
  四个属性
  - state状态(组件之间传递数据或组件的状态)
  - getters计算属性(将state中的某状态过滤后获取新状态)
  - mutations 存放如何更改状态,只能进行同步操作
  - actions commit mutations中方法来改变状态(不直接更改状态),可以进行异步操作。
*/
})

Vuex Store

  • 每一个Vuex应用的核心就是store仓库。实际上Vuex.Store()方法接收的是一个对象作为参数。而对象包含state,mutations,actions,getters四个属性。
    • state 用来存储所有组件公共数据
    • mutation 存放状态的变化,只能进行同步操作
      • 第一个参数是state,第二个参数是payload(自定义)
      • 只能使用store.commit(type, payload)来调用
    • getters 过滤公共数据,相当于store的计算属性
    • actions 解决异步改变共享数据,类似mutations,不同在于
      • actions提交的是mutations,而不是直接更改状态
      • actions可以包含异步操作
      • 使用store.dispatch(action,payload)来调用
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VUV6CtJ3-1574426063685)(./assets/vuex.png)]

ElementUI

  • 官网:https://element.eleme.cn/#/zh-CN
  • 安装:npm i element-ui -S
  • 引入:
    • 全部引入
      import ElementUI from 'element-ui';
      import 'element-ui/lib/theme-chalk/index.css';
      Vue.use(ElementUI);
      new Vue({
        el: '#app',
        render: h => h(App)
      })
      
    • 按需引入(借助 babel-plugin-component)
      • npm install babel-plugin-component -D
      • .babelrc:
        {
          "presets": [["es2015", { "modules": false }]],
          "plugins": [
            [
              "component",
              {
                "libraryName": "element-ui",
                "styleLibraryName": "theme-chalk"
              }
            ]
          ]
        }
        
      • 接下来,如果你只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容:
        import Vue from 'vue';
        import { Button, Select } from 'element-ui';
        import App from './App.vue';
        
        Vue.component(Button.name, Button);
        Vue.component(Select.name, Select);
        /* 或写为
        * Vue.use(Button)
        * Vue.use(Select)
        */
        

new Vue({
el: ‘#app’,
render: h => h(App)
});

  • Layout布局 24栅格系统
 
 <el-row :gutter="10">
   <el-col :span="6" class="bg-purple">javael-col>
   <el-col :span="6" class="bg-purple">webel-col>
   <el-col :span="6" class="bg-purple">Big Datael-col>
   <el-col :span="6" class="bg-purple">Pythonel-col>
 el-row>
 <el-row>
   <el-col :span="10" class="bg-purple">oneel-col>
   <el-col :span="10" :off-set="4" class="bg-purple">twoel-col>
 el-row>
div>
  • 常用容器组件
 <i class="el-icon-eleme" style="font-size:20px;color:blue;">i>
  <el-button type="primary">主要按钮el-button>
  <el-button type="success">成功按钮el-button>
  <el-button type="danger">危险按钮el-button>
  <el-button type="danger" plain>危险按钮el-button>
  <el-button type="danger" round size="mini">危险按钮el-button>
  <el-button type="danger" circle icon="el-icon-delete">el-button>
  <el-button type="primary" :loading="true">登录中el-button>
  <el-button type="primary" icon="el-icon-search">搜索el-button>
  <el-button type="primary">上传<i class="el-icon-upload el-icon--right">i>el-button>
  • 表单
<template>
  <div>
      <el-form label-width="80px" :model="user">
          <el-form-item label="账号">
              <el-input v-model="user.account"></el-input>
          </el-form-item>            
          <el-form-item label="密码">
              <el-input v-model="user.password" show-password></el-input>
          </el-form-item>      
          <el-form-item label="确认密码">
              <el-input v-model="user.confirmPass" show-password></el-input>
          </el-form-item>
          <el-form-item label="性别">
            <el-radio v-model="user.sex" :label="1"></el-radio>
            <!-- 数值 :label -->
            <el-radio v-model="user.sex" :label="0"></el-radio>
          </el-form-item>
          <el-form-item label="爱好">
          <el-checkbox-group v-model="user.hobby">
              <el-checkbox label="game">游戏</el-checkbox>
              <el-checkbox label="旅游"></el-checkbox>
              <el-checkbox label="编程"></el-checkbox>
              <el-checkbox label="购物"></el-checkbox>
          </el-checkbox-group>
          </el-form-item>
          <el-form-item label="居住地">
              <el-select v-model="user.home" placeholder="请选择">
                  <el-option label="杭州" value="hangzh"></el-option>
                  <el-option label="宁波" value="ningb"></el-option>
              </el-select>
          </el-form-item>
          <el-button @click="registe">登录</el-button>
      </el-form>
  </div>
</template>
<script>
export default {
  data(){
      return{
          user:{
              account:'',
              password:'',
              confirmPass:'',
              sex:1,
              hobby:[],
              home:''
          }
      }
  },
  methods: {
      registe(){
          console.log(this.user);
      }
  },
}
</script>
<style scoped>
</style>

你可能感兴趣的:(今天我想整理知识点,vue)