zoukankan      html  css  js  c++  java
  • Vue核心知识点

    一、vue.config.js 基本配置

    module.exports = {
      // 基本路径 cli3.3以前版本用baseUrl
      publicPath: '/',
      // 输出文件目录
      outputDir: 'dist',
      // 用于嵌套生成的静态资源
      assetsDir: '',
      // 生产环境sourMap
      productionSourceMap: false,
      // webpack配置
      configureWebpack: () => {},
      chainWebpack: () => {},
      
      // css相关配置
      css: {
        // 启动css modules
        modules: false,
        // 是否使用css分离插件
        extract: true,
        // 开启 css sourcemaps?
        sourceMap: false,
        // css 预处理器配置项
        loaderOptions: {}
      },
      
      // webpack-dev-server 相关配置
      devServer: {
        host: '0.0.0.0',
        port: 8080,
        proxy: {} // 设置代理
      },
      // 第三方插件配置
      pluginOptions: {
        // ...
      }
    }
    

    二、vue组件间传值

    1. 父子组件传值

    (1) props(父传子) / $emit(子传父)

    (2) $parent / $children

    // App => Father => Child
    // Father.vue
    mounted () {
      console.log(this.$children[0].val) // 访问子组件 Child 的某个数据(子传父)
      console.log(this.$parent.val) // 访问父组件 App 的某个数据(父传子)
      console.log(this.$parent.handleClick) // 也可以是某个方法
    }
    

    (3) $refs(访问具体DOM节点)

    ref 后面自定义节点名称,从而实现在 js 中访问,访问的方式是 this.$refs.自定义名称

    <!-- Father.vue -->
    <child ref="child"></child>
    
    // Father.vue
    mounted () {
      console.log(this.$refs.child)
    }
    

    2. 非父子组件传值

    (1) 事件总线

    原理:建立一个公有的 js 文件,专门来传递消息。

    // 在 util 文件夹下新建 bus.js
    import Vue from 'vue'
    export default new Vue()
    
    // 在需要传递消息或者接收消息的地方引入
    import bus from './bus.js'
    
    // 点击事件中传递自定义事件,发送消息
    bus.$emit('msg', val)
    
    // 监听事件,接收消息
    bus.$on('msg', val => {
      console.log(val)
    })
    

    (2) $attrs / $listeners

    爷传孙:$attrs 将父组件中不包含 props 的属性传入子组件,通常配合 inheritAttrs 选项一起使用。

    // 祖孙组件传值 App => Father => Child
    // App.vue 绑定属性将祖辈组件中 msg、title 传递给父组件
    <father :msg="msg" :title="title"></father>
    // Father.vue 在父组件上绑定 v-bind="$attrs" 
    <child v-bind="$attrs"></child>
    // Child.vue 孙子组件获取到祖父组件的数据
    mounted () {
      console.log(this.$attrs)
    }
    

    $listeners 监听子组件中数据变化,传递给父组件。(略)

    (3) vuex

    见第四章、第五章


    三、Vue Router

    1. 路由的基本配置

    (1) router 配置(路由懒加载)

    // index.js
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
      routes: [
        {
          path: '/home',
          name: 'home',
          component: () => import('../components/Home.vue') // 懒加载:动态导入,按需加载
        }
      ]
    })
    
    export default router
    

    (2) 路由视图

    App.vue,在合适的位置加上以下代码:

    <router-view></router-view>
    

    image-20200714115538669

    2. 路由的跳转

    <router-link to="/home">跳转</router-link>
    <router-view></router-view>
    

    (2) 编程式导航 this.$router.push( { ... } )

    <button @click="handleGo">js 跳转</button>
    <router-view></router-view>
    
    methods: {
      handleGo () {
        this.$router.push({
          path: 'home'
        })
      },
      // handleGo () {
      //  this.$router.push({
      //    name: 'home'
      //  })
      // }
    }
    

    3. 动态路由

    (1) 基本配置

    // router 目录下的 index.js
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
      routes: [
        {
          path: '/home/:id', // 动态路由,id 是自定义的参数名
          name: 'home',
          component: () => import('../components/Home.vue')
        }
      ]
    })
    
    export default router
    

    通过 $route.params.动态参数名 可以访问到动态参数:

    <!-- Home.vue -->
    <template>
      <div>
        <h2>Home 页</h2>
        <p>路由动态参数:{{$route.params.id}}</p>
      </div>
    </template>
    

    (2) 编程式导航的传参

    传参有两种形式,

    • 一种是查询字段的传参。(path + query)
    // App.vue (path + query)
    methods: {
      handleGo () {
        this.$router.push({
        	path: 'home',
        	query: {
            name: 'jack',
            gender: 'male',
            age: 18
          }
    		})
      }
    }
    

    点击跳转按钮后,数据被传递到了 url 中:

    image-20200714125955474

    • 一种是动态路由参数的传参。(name + params)
    // App.vue (name + params)
    methods: {
      handleGo () {
        this.$router.push({
          name: 'home',
          params: {
            id: 123
          }
        })
      }
    }
    

    image-20200714130306088

    4. 嵌套路由

    在 Home 页的一个区域显示一个路由页面,这个新的路由页面属于 home 路由,因此就要将它写在home路由规则下。

    Home.vue
    	|- Child.vue
    

    (1) 路由规则配置

    在 home 路由下添加 children 选项,配置新的路由规则。

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
      routes: [
        {
          path: '/home/:id',
          name: 'home',
          component: () => import('../components/Home.vue'),
          children: [ // 新路由 Child.vue 写在 children 选项下
            {
              path: '/child',
              component: () => import('../components/Child.vue')
            }
          ]
        }
      ]
    })
    
    export default router
    

    (2) 路由视图

    router-view 也理应写在 Home.vue 下。

    <!-- Home.vue -->
    <template>
      <div>
        <h2>Home 页</h2>
        <p>路由动态参数:{{$route.params.id}}</p>
        
        <!-- Child.vue 的视图将会在此处展示 -->
        <router-view></router-view>
        
      </div>
    </template>
    
    <script>
    export default {
      name: 'home'
    }
    </script>
    
    <style lang='stylus' scoped>
    
    </style>
    

    5. 导航守卫

    在 main.js 中加入以下代码:

    // main.js
    router.beforeEach((to, from, next) => {
      console.log('从这出发:', from.path)
      console.log('到达此处:', to.path)
      next()
    })
    

    在 '/' 处点击按钮后,跳转到 '/home/123'

    image-20200714131345920


    四、Vuex 基础用法

    公共数据仓库。

    image-20200714131651415

    • State
      • 数据
    • Mutations
      • 数据怎么变(同步)
    • Actions
      • 异步改变

    1. store 仓库创建

    // store 目录下的 index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      // 公共数据
      state: {
        count: 0
      },
      
      // 数据怎么变(同步):每个方法下都有一个参数 state 可以访问到公共数据
      mutations: {
        add (state) {
          state.count++
        },
        decrese (state) {
          state.count--
        }
      },
      
      // 异步修改数据:方法下有一个形参 context,通过 context.commit('变更方法名') 来提交变更方法,告诉它数据怎么变
      actions: {
        // 模拟异步操作
        delayAdd (context) {
          // 一秒后,调用 add 方法
          setTimeout(() => {
            context.commit('add')
          }, 1000)
        }
      }
    })
    

    2. 在视图中使用公共数据

    (1) 常规方式

    在需要用到公共数据的地方,通过计算属性引进 store 仓库中数据。

    通过 this.$store.state.数据名 可以获取到公共数据。

    // vue 实例
    computed: {
      count () {
        return this.$store.state.count
      }
    },
    
    <template>
      <div>
        <p>公共数据来了!它是:===> <span style="color:red">{{count}}</span></p>
      </div>
    </template>
    

    (2) 辅助函数:mapState

    https://vuex.vuejs.org/zh/guide/state.html#mapstate-%E8%BE%85%E5%8A%A9%E5%87%BD%E6%95%B0

    当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键。(注意,放在计算属性中!)

    import { mapState } from 'vuex' // 首先导入辅助函数 mapState
    
    export default {
      computed: {
        ...mapState({ // 通过展开运算符将对象展开
          // 传字符串参数 'count' 等同于 `state => state.count`
          count: 'count'
          
          // 箭头函数可使代码更简练
        	// count: state => state.count
        })
      }
    }
    

    关于展开运算符:https://blog.csdn.net/adsadadaddadasda/article/details/79391881

    3. 触发 Mutations 修改数据(同步)

    (1) 修改数据 this.$store.commit('xxx')

    <!-- html -->
    <p>公共数据来了!它是:===> <span style="color:red">{{count}}</span></p>
    <button @click="handleAdd">改变公共数据 (add)</button>
    
    // vue 实例
    // vue 组件 => commit('变更方法名') => Mutations => state => vue 组件
    methods: {
      handleAdd () {
        this.$store.commit('add') // 此时触发的就是 store 仓库中 Mutations 下的 add 方法
      }
    }
    
    // store 中的变更方法名
    mutations: {
      add (state) {
        state.count++
      },
      decrese (state) {
        state.count--
      }
    }
    

    (2) 辅助函数:mapMutation

    https://vuex.vuejs.org/zh/guide/mutations.html#%E5%9C%A8%E7%BB%84%E4%BB%B6%E4%B8%AD%E6%8F%90%E4%BA%A4-mutation

    你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。(注意,放在 methods 中!)

    import { mapMutations } from 'vuex' // 首先导入辅助函数 mapMutations
    
    export default {
      methods: {
        ...mapMutations({
          handleAdd: 'add' // // 将 this.handleAdd() 映射为 this.$store.commit('add')
        })
      }
    }
    

    4. 触发 Actions 修改数据(一般为异步)

    (1) 修改数据 this.$store.dispatch('xxx')

    <!-- html -->
    <p>公共数据来了!它是:===> <span style="color:red">{{count}}</span></p>
    <button @click="handleAdd">改变公共数据 (add)</button>
    
    // vue 实例
    // vue 组件 => dispatch('异步方法名') => Actions => commit('变更方法名') => Mutations => vue 组件
    methods: {
      handleAdd () {
        this.$store.dispatch('delayAdd')
      }
    }
    
    // store 中的 actions 异步方法名
    actions: {
      delayAdd (context) {
        // 一秒后,调用 Mutations 中的 add 方法
        setTimeout(() => {
          context.commit('add')
        }, 1000)
      }
    }
    

    (2) 辅助函数:mapActions

    https://vuex.vuejs.org/zh/guide/actions.html#%E5%9C%A8%E7%BB%84%E4%BB%B6%E4%B8%AD%E5%88%86%E5%8F%91-action

    你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store(注意,放在 methods 中!)

    import { mapActions } from 'vuex'
    
    export default {
      methods: {
        ...mapActions({
          handleAdd: 'delayAdd' // // 将 this.handleAdd() 映射为 this.$store.dispatch('delayAdd')
        })
      }
    }
    

    五、Vuex 高级用法

    1. Vuex 中的计算属性:Getters

    getters 中的数据依赖于 state 中的数据。

    // store
    state: {
      count: 0
    },
    getters: {
      doubleCount (state) {
        return state.count * 2
      }
    }
    

    (1) 常规方式

    <!-- html -->
    <p>公共数据来了!它是:===> <span style="color:red">state: {{count}}</span></p>
    <p>公共数据来了!它是:===> <span style="color:green">getters: {{doubleCount}}</span></p>
    <button @click="handleAdd">改变公共数据 (add)</button>
    
    // vue 实例
    computed: {
    	// ...
      doubleCount () {
        return this.$store.getters.doubleCount
      }
    }
    

    当点击按钮时,state.count++,因为 doubleCount 依赖于 state.count,因此会同时发生计算。

    (2) 辅助函数:mapGetters

    https://vuex.vuejs.org/zh/guide/getters.html#mapgetters-%E8%BE%85%E5%8A%A9%E5%87%BD%E6%95%B0

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

    import { mapGetters } from 'vuex'
    
    export default {
      computed: {
        // ...mapGetters(['doubleCount']) // 参数名和方法名一致
        
        ...mapGetters({
          doubleCount: 'doubleCount'
        })
      }
    }
    

    2. 模块化:Modules

    各个模块各司其职,管理自己的数据。

    由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

    为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

    https://vuex.vuejs.org/zh/guide/modules.html#module

    (1) 模块分离

    • 在 store 文件夹下新建一个 js 文件(模块),将这个模块起名为 handleCount。
    // handleCount.js
    // handleCount模块
    export default {
      state: {
        count: 0
      },
      getters: {
        doubleCount (state) {
          return state.count * 2
        }
      },
      mutations: {
        add (state) {
          state.count++
        },
        decrese (state) {
          state.count--
        }
      },
      actions: {
        delayAdd (context) {
          // 一秒后,调用 add 方法
          setTimeout(() => {
            context.commit('add')
          }, 1000)
        }
      }
    }
    
    • 引入 index.js 主模块中
    import Vue from 'vue'
    import Vuex from 'vuex'
    import handleCount from './handleCount' // 引入模块 handleCount
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      modules: {
        handleCount
      }
    })
    

    因为使用了模块,所以原来的 state 指向都会发生变化。

    例如访问 count 数据,不再是 this.$store.state.count,而是 this.$store.state.handleCount.count。(this.$store.state.模块名.数据名)

    • 使用箭头函数
    // vue 实例中的 computed 选项
    ...mapState({
      count: state => state.handleCount.count
    })
    

    (2) 命名空间

    如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

    https://vuex.vuejs.org/zh/guide/modules.html#%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4

    // handleCount 模块
    export default {
      namespaced: true, // 添加命名空间字段,其他照旧
      // ...
    }
    
    

    当添加了命名空间选项时,所有的辅助函数的映射效果就会发生错误,这时要手动调整过来:

    // 原代码:
    // computed
    ...mapGetters({
      doubleCount: 'doubleCount'
    })
    // methods
    ...mapActions({
      handleAdd: 'delayAdd'
    })
    
    // <=============================================================================================>
    
    // 调整后:
    // computed
    ...mapGetters({
      doubleCount: 'handleCount/doubleCount'
    })
    // methods
    ...mapActions({
      handleAdd: 'handleCount/delayAdd'
    })
    

    关于命名空间:https://blog.csdn.net/lzb348110175/article/details/89387495


    六、Element UI

    1. 安装依赖

    cnpm i element-ui --save
    

    --save 表示依赖包被安装到了生产环境中。(简写 -S)

     i  是 install 的简写
    -S 就是 --save 的简写
    -D 就是 --save-dev 的简写
    
    npm i module_name -S = > npm install module_name --save 写入到 dependencies 对象
    
    npm i module_name -D => npm install module_name --save-dev 写入到 devDependencies 对象
    
    npm i module_name -g 全局安装
    

    关于指令:https://www.cnblogs.com/del88/p/13272767.html

    2. 引入 Element

    // main.js
    import Vue from 'vue'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    import App from './App.vue'
    
    Vue.use(ElementUI)
    
    new Vue({
      el: '#app',
      render: h => h(App)
    })
    

    3. 布局组件使用

    <h3>div块 4等分布局</h3>
    <el-row :gutter="20">
      <el-col :span='6'><div class="content">1</div></el-col>
      <el-col :span='6'><div class="content">2</div></el-col>
      <el-col :span='6'><div class="content">3</div></el-col>
      <el-col :span='6'><div class="content">4</div></el-col>
    </el-row>
    
    <h3>整块页面布局</h3>
    <el-container>
    	<el-header>Header</el-header>
    	<el-main>Main</el-main>
    	<el-footer>Footer</el-footer>
    </el-container>
    

    gutter 表示间隔,span 表示占用份数。(一行共 24 份)

    el-header el-aside el-main el-footer 的父容器只能是 el-container,el-container 的子容器也只能是前四者。


    七、弹出类型组件

    1. Dialog 对话框

    https://element.eleme.cn/2.0/#/zh-CN/component/dialog#dialog-dui-hua-kuang

    <template>
      <div>
        <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>
    
        <el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
          <span>这是一段信息</span>
          <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false">取 消</el-button>
            <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
          </span>
        </el-dialog>
      </div>
    </template>
    
    <script>
    export default {
      name: 'pop',
      data () {
        return {
          dialogVisible: false
        }
      },
      methods: {
        handleClose (done) {
          this.$confirm('确认关闭?')
            .then(_ => {
              done()
            })
            .catch(_ => {})
        }
      }
    }
    </script>
    
    <style lang='stylus' scoped></style>
    

    2. Popover 弹出框

    https://element.eleme.cn/2.0/#/zh-CN/component/popover#popover-dan-chu-kuang

    <el-popover
      ref="popover1"
      placement="top-start"
      title="标题"
      width="200"
      trigger="hover"
      content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。">
    </el-popover>
    <el-button v-popover:popover1>hover 激活</el-button>
    

    八、表格组件

    1. 基础表格

    <el-table
    	:data="tableData"
    	style=" 100%"
    	height="500"
    	border
    >
      <el-table-column
    		prop="date"
    		label="日期"
         width="180">
      </el-table-column>
      <el-table-column
    		prop="name"
    		label="姓名"
    		width="180">
      </el-table-column>
      <el-table-column
    		prop="address"
    		label="地址">
      </el-table-column>
    
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button
    				size="mini"
             @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
          <el-button
    				size="mini"
             type="danger"
             @click="handleDelete(scope.$index, scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    export default {
      name: 'tableList',
      data () {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]
        }
      },
      methods: {
        handleEdit (index, row) {
          console.log(index, row)
        },
        handleDelete (index, row) {
          console.log(index, row)
        }
      }
    }
    

    2. el-table 表格常用属性

    属性名 作用
    height 给表格设置高度,同时固定表头。
    show-header 设置是否显示表头。
    row-class-name 设置一个函数或者固定的名字作为行的类名。
    border 是否显示表格竖直方向的边框,设置后可通过改变边框来设置列宽。

    3. el-column 列常用属性

    属性名 作用
    label 当前列的表头名称
    prop 传入的表格 json 数据的 key 值
    show-overflow-tooltip 是否设置文字超出列宽时悬浮显示完整内容

    4. 通过 v-for 封装更好的表格

    <el-table :data='tableData'>
      <el-table-column v-for="(val, key) of tableLabel" :key='key' :prop='key' :label='val'></el-table-column>
      
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button
    				size="mini"
             @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
          <el-button
             size="mini"
             type="danger"
             @click="handleDelete(scope.$index, scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    export default {
      name: 'tableList',
      data () {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }],
          tableLabel: {
            date: '日期',
            name: '姓名',
            address: '地址'
          }
        }
      },
      methods: {
        handleEdit (index, row) {
          console.log(index, row)
        },
        handleDelete (index, row) {
          console.log(index, row)
        }
      }
    }
    
  • 相关阅读:
    C#操作EXcel
    ADO.NET 导出 Excel 文件
    基于jQuery的数字键盘插件
    Python爬虫(三)——正则表达式
    python爬虫(二)——第一个爬虫程序
    python爬虫学习(一)——爬虫的工作原理
    斜率优化DP学习笔记
    可持久化线段树学习笔记
    尺取法学习笔记
    分层图学习笔记
  • 原文地址:https://www.cnblogs.com/buildnewhomeland/p/13307856.html
Copyright © 2011-2022 走看看