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
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