• vue 学习记录 [记录]


    vue-cli 脚手架
    
    
    vue-router 管理视图
    
        安装 + 嵌套 + 视图切换 + 按需加载
    
        开始使用vue-router
            i.安装模块 npm install vue-router --save
            ii.引入模块 import VueRouter from 'vue-router'
            iii.作为Vue插件 Vue.use(VueRouter)
            iv.创建路由实例对象 new VueRouter({...配置参数})
            v.注入vue选项参数 new Vue({router})
            vi.告诉路由渲染位置 <router-view></router-view>
    
    
    Vuex 状态管理
    
    
    axios 数据请求
    
        拦截 + promise + api
    
    
    
    
    
    *****************************************************************************************************************
    *****************************************************************************************************************
    
    <router-link to='/path'></router-link>
    <router-link :to='动态字段名url'></router-link>
    <router-link :to='{path:"/path"}'></router-link>
    
    <router-link to='/path' tag='div'></router-link>  生成div 而不是a  (最常见 ul>li tag=li)
    
    改变行为 event 鼠标移入切换而不是点击 <router-link to='/path' event='mouseover'></router-link>
    
    new VueRouter
        mode  history
        linkActiveClass  你想要的激活className   (单个要求别的颜色<router-link to='/path' active-class="你要的激活className"></router-link>)
    
    设置统一样式
        <router-view class='统一样式className'></router-view>  组件根节点div上(template>div) 继续加
    
    重定向
        path:*  component:404
        path:*  redirect:'/home'  =  redirect:{path:'/home'}  =   redirect:{name:'Home'} 
                动态设置目标 redirect:(to)=>{
                    动态设置目标  console.log(to)
                    to = 目标路由对象,就是访问的路径的路由信息
                    to.path
                    return 一个目标 '/home' || {path}  ||  {name}
                }
    别名
        alias:'/index'
    exact
        / = home  激活状态 <router-link to='/' exact></router-link> exact精确匹配
    
    
    <router-link to='/path' tag='li'><a>111</a></router-link>  to里面的路径会自动到a上
    
    子路由 children:[]
        不要斜杠  /是以跟路由来的(如果需要 /a/b = /b  则加/)
        设置默认子路由 path:''  直接空
        name 可以直接给默认子路由
        <router-link :to='{name:"防止过多层路径/a/b/c/d"}' tag='li'><a>111</a></router-link> 
    
    
    多视图
        一个路径对应多个组件 components:{defalut没名字的视图:组件名,视图名:组件名}   <router-view name='视图名'></router-view>
    
    滚动行为
        router里面  scrollBehavior(to,from,savePosition){
            点击浏览器的前进后退或者切换导航触发
            to 要进入的目标路由对象 | from 离开的路由对象 | savePosition 滚动条坐标  点击前进后退的时候才有值
            I. if(savePosition){ return savePosition; }else{ return {x:0,y:0} }
            II. 定位到锚点 if(to.hash){ return { selector: to.hash } }   /a#id
        }
    
    
    动态路径
        /a/:id   获取参数:路由对象的params
        path:'/user/:userId?'  = /a/1 /a  /a/2   '/user:vip?/:userId?' 
        获取  编译之前拿 created(){ this.$router   this.$router.params.userId }
            query url查询对象 | params 动态路由参数
    
    created
        组件复用  created 不在进行一次 - 解决 监听
        当访问user  组件会生成一次  生成一次之后  leo1,2,3 都处于复用  钩子函数 不会执行
        watch:{
            $route(){  // 路径发生变化 $route 会重新赋值 监控这个属性 会执行这个函数
                console.log(this.$router.params.userId)
                getData()
            }
        },
        created(){...getData()}   created 
        // 渲染这个组件会调用一次这个生命周期 
        // + 复用这个组件 这个函数不会再次被调用 
        // + 地址一旦发生变化 $route会重新生成一个路由信息对象
        methods:{
            共同方法放置  getData(){}
        }
    
    查询字符串
        /a?info=follow    /a?info=share
        <router-link exact to='?info=follow'></router-link>
        <router-link exact :to='{path:'',query:{info:'follow'}}'></router-link>     $route.query
    
    
    过渡动画
        tansition + 添加删除css
        v-enter
        <transition>包上要运动元素router-view</transition>
        .v-enter{opacity:0} + .v-enter-to{opacity:1} + .v-enter-active{transition:1s}    ----+ .v-leave{opacity:1} + .v-leave-to{opacity:0} + .v-enter-leave{transition:2s}    ----  出
    
         一个还没消失 一个就已经出现 - 解决:定位在同一个位置  (离开和进入同时进行)
        过度模式:in-out(新元素过渡--完成后当前元素过渡离开)
                  out-in(当前元素--后新元素进入)
                  <transition mode='out-in'>
    
         .left-enter{transform:translateX(100%)} + .left-enter-to{transform:translateX(0)} + .left-enter-leave{transition:1s}    ----  右入
         ...  0  -100%  1s      0两个目标可以不用写 默认
         <transition name='left'>  会把left做成前缀 去找enter enter-to enter-leave  | mode='out-in' 不要 同时运行
    
         左右滑 - 下标 或  router设置自己的meta   $.route.meta
         watch:{
            $route(to,from){
                to.meta.index  比较  from.meta.index  给个动态name
            }
        },
    
    
    前进后退
        back 回退一步   this.$router.back()
        forward 前进一步
        go 指定前进后退步数 this.$router.go(-1)   超出无效  this.$router.go(2)   0刷新当前页
        push 控制指定的导航(新添加一条记录) this.$router.push('/home')   ({})
        repalace 替换当前history栈中当前记录 this.$router.repalace({path:'/home'})
    
    
    导航钩子函数
        router.beforeEach((to,from,next)=>{
            console.log('beforeEach')  想要进入导航需要执行next()
            next里面可以传参   (false)不执行
            login可进入  meta打标签是否需要登录  to.meta.login --  next('/login')  重定向去login
        })
        router.afterEach((to,from)=>{
            console.log('afterEach')  改变title    window.document.title = to.meta.title
        })
        全局钩子(beforeEach+afterEach) +单个路由里面 beforeEnter+ 单个组件钩子(beforeRouteEnter  .vue里面export default里面 一样写)
        vue页面里面的 beforeRouteEnter 里面的this指向问题  -  路由钩子先执行然后组件钩子 组件实例没创建 this==undefined
            解决:写回调   beforeRouteEnter(to,from,next){next(vm=>{vm.test='改变test'})}
            当一级导航里面拥有二级导航 此时 导航更新 beforeRouteUpdate(to,from,next)
            离开组件 beforeRouteLeave(to,from,next)
    
    
    项目
        assets > css建议抽离出 + img    css抽离后  @import  css包含css  | import  js包含css
        components > 公共组件
        view > 视图页面  + layout
        lib > 库 + 公共utils
        router > 路由
        
        登录
            每个页面都需要引入utils - 解决:作为vue插件引入   用this去访问
             => Vue.use(Router)  this.$router   放在根实例上  new Vue({el:#app....})
             => main.js Vue.prototype.$自定义属性名uuu = '自定义属性名uuu'   在组件里面  this.自定义属性名uuu 可以获取到
             => 那么   let obj={但是要遵循原则key  install:function(Vue,options){}}  Vue.use(obj,可以带自己参数) options为自己参数
                 install:function(Vue,options){
                     Vue.prototype.$uuu = 'uuu'
                 }
    
             Vue插件 用来获取和设置localStorage存储
             let local={
                 save(key,value){localStorage.setItem(key,JSON.stringify(value))},
                 fetch(key){return JSON.parse(localStorage.getItem(key))||{}}
             }
             export default{
                 install:function(vm){
                     vm.prototype.$local = local  把东西挂于原型身上
                 }
             }
             用  import引入Untils  Vue.use(Untils)   -- 组件上 this.$local
    
        vue中input 通过ref='nameUUU'找到这个元素  
            获取input值 this.$refs.nameUUU
            存储this.$local.save('key',{login:true,userName:username})
            之后跳转首页this.$router.push('/')
    
        
        是否需要登录 router.beforeEach
        + meta
            自己meta + 父级meta   router.beforeEach(to.matched.some(item=>item.meta,login)?(登录?next():登录):next())
            some 只要有一个匹配 返回true
            是否登录  不能用this  -- 解决:router.app指向根实例 router.app.$local.fetch('key')
        + 记住登录前的页面
            router.push({
                path:'/login',
                query:{
                    redirect:to.path.slice(1)
                }
            })
    
        滚动动画
            <router-link :to="{path:'#abc'}">1111</router-link>
            doc a id=abc href=#abc
            mpn i tween.js --save
            beforeRouteUpdate(to,from,next){
                this.animate(to);next();
            }
            methods:{
                animate(to){
                    function animateFunc(time){
                        requestAnimationFrame(animateFunc)
                        TWEEN.update(time)
                    }
                    if(to.hash){
                        var el = document.getElementById(to.hash.slice(1))
                        var doc = document.getElementByClassName("doc")[0]
                        if(el){
                            animateFunc()
                            new TWEEN.Tween({number:doc.scrollTop开始位置}).to({number:el.offsetTop结束位置},持续500).onUpdate(function(){doc.scrollTop=this.number.toFixed(0)}).start()
                        }
                    }
                }
            }
    
        懒加载 按需加载
            当路由被访问的时候才加载对应的组件
            如 layout 里面的 header
                components:{
                    headerNav:(resolve)=>{
                        setTimeout(()=>{
                            // i import Header + resolve(Header)
                            resolve(Header)
                            // ii require
                            resolve(require('url'))
                        },2000)
                    }
                }
            如 router里面懒加载
                layout = resolve => require.ensure(['./page/linkParamsQuestion.vue']依赖是数组, ()=>{resolve(require(url))})
            按功能切 两个组件切成一个组件
                layout = resolve => require.ensure(['./page/linkParamsQuestion.vue']依赖是数组, ()=>{resolve(require(url))},'abc')
                当看到trunk abc  将都为abc的打包在一起
            可以直接使用import!!!
                layout = resolve => import('组件url')  但是 import不支持第二个参数 没办法将两个组件js打包成为一个
    
        打包的时候如果需要将路径配置进去
            config>index.js > assetsPublicPath:'/根据自己需求更改'
            单页面应用只有一个index.html http:sss/uuu 需要指向index -- 解决:服务端配置
            Nginx配置:
                location /{
                    root /home/我的应用根目录
                    try_files $uri $uri/ /index.html =404
                }
    
    
    Vuex 兄弟组件共享数据
        什么情况使用:多视图依赖同一个状态 || 来自不同视图需要变更同状态
        仿select  下拉菜单
        F   :is-show.sync='listShow'
        C   this.$emit('update:is-show','uuu')
            获取初始值 props:['isShow']  --> 计算初始 computed:{ initShow(){return this.isShow} } --> 操作 this.$emit('update:is-show',!this.initShow())
        F -> C  :data="data"  props:['data']
        C 触发 F 组件事件  this.$emit('事件名',传值)
    
        npm install vuex --save  +  Vue.use(Vuex)  + 定义容器 new Vuex.Store()  +  注入根实例 {store}
        store > index.js
        new Vuex.Store({state:{count:100}})   子组件获取值 this.$store.state.count
        改变值 store 不能直接改变store中的状态 唯一途径提交mutations
        new Vuex.Store({
            state:{
                count:100
            },
            mutations:{
                add(state){state.count++}
            }
        })
        页面提交mutation   this.$store.commit("add")
            this.$store.commit("add",自己参数)   add(state,n){state.count+=n}  参数尽量为{} 防止多参数
            或者直接传对象 this.$store.commit({type:'add',n:5})   add(state,payload)
        提交mutation 必须是同步的 必须立马变化 如果一定要通过ajx改变状态 -- 解决:actions
            actions:{
                addA(context){
                    setTimeout(()=>{
                        // 改变状态 提交 mutation
                        context.commit('add',{n:5})
                        还可以继续触发 context.dispatch('addA2',{n:5})
                    },1000)
                }
            } 那么点击之后不能直接触发commit而是触发action   this.$store.dispatch('addA')
            可以解构赋值
                addA({commit,dispatch}){
                    setTimeout(()=>{
                            commit('add',{n:5})
                            dispatch('addA2',{n:5})
                        },1000)
                }
        getters:{
            对状态进一步处理 超过120不再加
            函数filterCount(state){
                return state.count>=120?120:state.count 
            }
        }那么组件里面 num2(){return this.$store.getters.filterCount} 去getters取值
        Vuex 流程图
    
    
        辅助函数
        要用到辅助函数  import {mapState,mapGetters,mapActions,mapMutation } from 'vuex'  解构赋值 引入
        computed:mapState({
            // num:state=>state.count
            // num:'count'
            // num(state){return state.count + 100}
            // count:'count'
        })
        computed:mapState(['count'])
        computed:{
            abc(){return 123},
            ...mapState(['count'])
            ...mapState({num2:'filterCount'})
        }
        methods:{
            ...mapActions({
                clickName:'要触发的name addA'
            }),
            ...mapMutation({
                clickName:'要触发的name add'   传参@clickName(这里可以直接传参)
            })
        }
    
        axios   - npm run axios
            import axios from 'axios'
            为了别的地方也要用 + 写异步里  axios.get(url).then((data)=>{console.log(data)}).catch((error)=>{错误})
    
    
    
    
    
    
    
    *****************************************************************************************************************
    *****************************************************************************************************************
    
    
    
    Vue
    
    //https://segmentfault.com/a/1190000009651628
    config/index.js
        port
        assetsPublicPath ./
    
    
    组件懒加载
        component: resolve => require(['./page/linkParamsQuestion.vue'], resolve)
        不用import 访问到这个页面的时候才会去加载相关资源,提高页面的访问速度
    
    
    router传参数
        1.路由匹配参数
            { path: '/user/:id', component: User }
            对 /user/的路径做拦截,后面的内容会被映射成id参数
            let id = this.$route.params.id;
            /user/:username/post/:post_id
        2.Get请求传参
            http://localhost:8080/linkParamsQuestion?age=18
            let age = this.$route.query.age;
    
    
    编程式导航
        1.<router-link>创建可跳转链接
            <router-link to="/linkParams/xuxiao">a链接</router-link>
        2.方法里this.$router.push('xxx')跳转
            I. this.$router.push('home')
                // 字符串,这里的字符串是路径path匹配,不是router配置里的name
            II. this.$router.push({ path: 'home' })
                // 对象
            III. this.$router.push({ name: 'user', params: { userId: 123 }})
                 = this.$router.push({path: `link/${id}`})
                // 命名的路由 这里会变成 /user/123
            IV. this.$router.push({ path: 'register', query: { plan: 'private' }})
                // 带查询参数,变成 /register?plan=private
    
    导航钩子
        导航跳转的时候做一些操作(eg:登录的拦截 | 权限)
        1.全局
            router.js - 全局性的路由拦截
            router.beforeEach((to, from, next)=>{do something;next();});
            router.afterEach   没有next函数
            可以配合 meta  做标记 (eg:哪些页面需要登录)
        2.路由独享
            单个路由的跳转拦截
            {path: '/foo',component: Foo,beforeEnter: (to, from, next) => {...}}
        3.组件内
            beforeRouteEnter | beforeRouteUpdate | beforeRouteLeave
    
    
    computed
        computed: {
            // 区别在于 method   
            // 如果 name 没有被修改,下次 get 不会进行重复计算,而 method 则每次调用都会重新计算
            hdlName: function () {  // `this` 指向 vm 实例
              return this.name + '---- 这是 处理之后的字段'
            },
            fullName: {
                // getter setter 解释: http://www.cnblogs.com/chinajins/p/5996835.html
                // ≈ watch | Watcher主要应用场景是异步或耗时操作
                get: function () { 
                    // getter
                },
                set: function (newValue) { 
                    // setter 
                }
              }
    
        }
    
    methods
        methods: {
            go: function () {
              this.$router.push({path: `link/123`})
            }
          }
    
    
    <input type="text" v-model="name">
    class
        v-bind:class="[activeClass, errorClass]"
        v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"
    v-if
        01. v-if 是 lazy 的,不会渲染没有走到的条件
        02. 切换后原来的 dom 会被 destroyed
        <h1 v-if="ok">Yes</h1>
        <h1 v-else>No</h1>
        <template v-if="ok">...</template>
    v-show
        <h1 v-show="ok">Hello!</h1>  | v-show 不支持 template 和 v-else
    v-for
        <li v-for="(item, index) in items">...</li>
        <template v-for="item in items">...</template>
        v-for 遍历对象:
            属性value:<li v-for="value in object">{{ value }}</li>
            key: <div v-for="(value, key) in object">{{ key }} : {{ value }}</div>
            index:<div v-for="(value, key, index) in object">{{ index }}. {{ key }} : {{ value }}</div>
        v-for="n in 10"
        处理 过滤/排序
            ≈  computed + filter
            <li v-for="n in even(numbers)">{{ n }}</li>
            methods: {
              even: function (numbers) {
                return numbers.filter(function (number) {
                  return number % 2 === 0
                })
              }
            }
    v-on 
        调用 methods 中定义的事件
            $event 
        事件修饰符
            <input v-on:keyup.13="submit">
            <input v-on:....13="submit">
        Key 修饰符
            <a v-on:click.stop="doThis"></a>
            <a v-on:click....="doThis"></a>
    表单
        v-model="message"
            修饰符
            <input v-model.lazy="msg" > 加上 lazy 修饰符后就会在 change 事件后才同步
            v-model.number
            v-model.trim
        Checkbox   
            <input type="checkbox" value="Mike" v-model="checkedNames">Mike
            <input type="checkbox" value="John" v-model="checkedNames">John
            <input type="checkbox" v-model="toggle" v-bind:true-value="666" v-bind:false-value="999">----{{toggle}}    
        Radio
            <input type="radio" value="One" v-model="picked">One
            <input type="radio" value="Two" v-model="picked">Two
        Select
            <select v-model="selected">
              <option>A</option>
              <option>B</option>
            </select>
            多选 multiple
            v-for <option v-for="option in options" v-bind:value="option.value">{{ option.text }}</option>
    
    
    <style></style>属性可进行配置,scoped表此样式只在当前页面有效。lang="xxx"支持less/sass语法规则
    
    
    created () {
        /* 这个是vue的钩子函数,当new Vue()实例创建完毕后执行的函数 */
        this.$http.get('/api/goods').then((data) => {
          /* 调用vue的ajax来请求数据,promise语法,并用es6的箭头函数 */
          this.items = data.body.data
        })
      }
    
    
    
    
    
    
    
    https://segmentfault.com/a/1190000008010666
    
    
    
    
    
    
    案例学习:
        head + body + foot
        body > ul > li   -->   li 为一个组件 传参入
    
        li 作为组件
            template > li  props
            {{ price|dTofixed|dCurrency }}
        html
            import XXX from 'XXX'
            const appData = require('goods.json')
                created () {this.items = appData.goods}
            template v-for="item in items"
                <list :price="item.price" :title="item.title" :img="item.img"></list>
        notice
            <template lang="html">
            <style lang="css" scoped>
            src > assets + components + pages
    # install vue-cli
    $ npm install -g vue-cli
    # create a new project using the "webpack" boilerplate
    $ vue init webpack my-project
    # install dependencies and go!
    $ cd my-project
    $ npm install
    $ npm run dev
    CLI

     https://segmentfault.com/a/1190000008010666

    ---------------------------------------------------------------------------------------------------------

    yarn

      http://blog.csdn.net/guoquanyou/article/details/61199935

      npm install -g yarn

     浅学Vue

      index html  |    因为在 index.html 里面定义了<div id="app"></div>所以就以这个组件作为主入口

      main js   |

        import 导入相关内容  vue  + app.vue 页面   +  相关路由 + webpack配置文件

        相关配置

         路由器会创建一个 App 实例,并且挂载到选择符 #app 匹配的元素上。

      路由  router  |

        引入模块  ---   注册

        引入页面  ---  配置路由        

          import 'element-ui/lib/theme-chalk/index.css'
          import vuetest01 from '@/components/th/vuetest01' 

        引入css  报错  |  webpack 打包的时候无法识别并转换成 js,所以就需要配置才能读取 css 和字体文件  |   yarn add style-loader --save-dev  +  yarn add css-loader --save-dev + yarn add file-loader --save-dev

        定义组件 1  

          const First = { template: '<div><h2>我是第 1 个子页面</h2></div>' }

    使用路由搭建单页应用

      安装vue-router    ----   yarn add vue-router --save

          import Router from 'vue-router'     注册   Vue.use(Router)

      ajax请求 请求外部数据以动态改变页面内容   -------------   yarn add vue-resource --save

          import VueResource from 'vue-resource'  注册  Vue.use(VueResource)

    package.json 里 devDependencies和dependencies的区别

      npm install 安装模块或插件 命令把他们写入到 package.json 文件里

      --save-dev   安装的 插件,被写入到 devDependencies 对象里面  |  devDependencies  里面的插件只用于开发环境,不用于生产环境  |  开发的时候需要的依赖项,像一些进行单元测试之类的包。

      --save  安装的插件,责被写入到 dependencies 对象里面  |  dependencies  是需要发布到生产环境的。 |  依赖的项该是正常运行该包时所需要的依赖项

    版本号

      github  packageJson

  • 相关阅读:
    设计模式之抽象工厂模式
    MQ任意延时消息(三)基于服务端实现
    MQ任意延时消息(二)基于客户端实现
    MQ任意延时消息(一)实现原理概述
    sqlyog报错2058
    base标签的作用
    相对路径和绝对路径的解释
    自定义Tomcat部署目录
    常用正则表达式
    接口的结构定义
  • 原文地址:https://www.cnblogs.com/caiCheryl/p/7805078.html
Copyright © 2020-2023  润新知