vue 学习记录 [记录]

时间:2022-10-23 00:20:40

 

 

 

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

 

vue 学习记录 [记录]vue 学习记录 [记录]
# 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

vue 学习记录 [记录]

 

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

 

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