• VUE开发篇


    VUE开发

    快速原型开发

    可以使用 vue serve 和 vue build 命令对单个 .vue 文件进行快速原型开发。但是需要先安装@vue/cli-service-global插件。

    npm install -g @vue/cli-service-global
    

    新建一个.vue文件,然后启动一个服务并运行原型:

    vue serve 文件名.vue
    

    脚手架创建项目

    官方地址

    vue create
    vue create my-vue
    

    选择Default ([Vue 2] babel, eslint)就可以了。

    如果想要自己配置,那么可以选择第三个:

    默认还是选择了默认配置babel、linter,其它的根据自己需求选择。

    enter下一步:(2.x版本和3.x版本的选择)

    enter下一步进入EsLint配置:(很严格还是只是在命令行中给提示,建议选择默认的第一个)

    enter下一步:(保存的时候做Lint还是提交的时候)

    enter下一步:(配置文件的选择)

    然后执行:

    cd 项目名

    yarn serve

    然后浏览器中打开http://192.168.8.132:8080/就可以看到欢迎界面。

    项目文件说明:

    vue ui

    图形化项目管理:

    vue ui
    
    安装插件

    Vue CLI 使用了一套基于插件的架构。插件可以修改 webpack 的内部配置,也可以向 vue-cli- service 注入命令。在项目创建的过程中,绝大部分列出的特性都是通过插件来实现的。

    在一个已经被创建好的项目中安装一个插件,可以使用 vue add 命令。例如安装路由插件:

    vue add router
    

    (然后会提示你现在有代码变的操作)

    输入y继续:

    然后再输入y,插件添加成功。

    (添加插件,可能会对项目进行破坏性地结构上的变更,甚至是文件内容的修改。例如查看main.js和App.vue。所以其实最好把安装之前的版本给备份一下。)

    处理资源路径

    当你在 JavaScript、CSS 或 *.vue 文件中使用相对路径 (必须以 . 开头) 引用一个静态资源时,该资源将被webpack处理。

    转换规则:

    • 如果 URL 是一个绝对路径 (例如 /images/foo.png ),它将会被保留不变。

      <img alt="logo" src="/assets/pyy.png"> // 会在public文件夹中去找,名字不会被改动:webpack不会对public做任何操作
      <img alt="pyy" src="https://www.baidu.com/xxx/pyy.png"> // 图片服务器中的地址访问 
      
    • 如果 URL 以 . 开头会作为一个相对模块请求被解释并基于文件系统相对路径。

      // 会被webpack编译(打开检查器查看图片src,我们可以看到最终编译的结果是文件的hash)
      // 关于图片webpack做的操作:  图片都会有批量的处理,把它作为资源、模块来做处理,如果足够小,会把它变成url路径,做字符串的编码。如果足够大,会起一个合适的名字,放到一个合适的地方去。 
      <img alt="logo" src="./assets/pyy.png">
      
    • 如果 URL 以 @ 开头会作为一个模块请求被解析。Vue CLI 默认会设置一个指向 src 的别名 @ 。

      <img alt="logo" src="@/assets/pyy.png"> // @代表src根目录
      
    • 扩展:如果 URL 以 ~ 开头会作为一个模块请求被解析。这意味着甚至可以引用 Node 模块中的资源(node_modules中的)

      <img src="~xxx-npm-package/pyy.png">
      

    那么何时使用public文件夹呢?

    通过 webpack 的处理并获得如下好处:

    • 脚本和样式表会被压缩且打包在一起,从而避免额外的网络请求。

    • 文件丢失会直接在编译时报错,而不是到了用户端才产生 404 错误。

    • 最终生成的文件名包含了内容哈希,因此不必担心浏览器会缓存它们的老版本。

    使用public的场景:

    • 需要在构建输出中指定一个固定的文件名字。

    • 有非常多的图片,需要动态引用它们的路径。

    • 需要考虑兼容性,使用script标签引入。

    注意:

    如果应用打包上传到服务器之后,没有部署在域名的根部,那么需要配置publicPath前缀:

    在项目最外层,加上一个vue.config.js文件,文件中添加如下代码:

    module.exports = { 
    	// 判断当前运行环境 是生产环境还是开发环境 
    	// 生产环境时加上/部署服务器中的文件夹名/, 开发环境时就不添加 
      publicPath: process.env.NODE_ENV === 'production'? '/部署服务器中的文件夹名/': '/' 
    }
    
    预处理器

    如果创建项目时没有选择需要的预处理器(Sass/Less/Stylus),则需手动安装相应loader。

    # Sass 
    yarn add sass-loader node-sass 
    # Less 
    yarn add less-loader less 
    # Stylus 
    yarn add stylus-loader stylus
    

    安装完成了,就可以使用了。

    <style scoped lang='scss'>
      $color: green; 
      h1 { 
        color: $color; 
      }
    </style>
    

    注意:当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素,其原理是通过使用PostCSS 来实现转换。

    <template> 
    	// 给标签添加自定义属性 data-v-f3edg9
    	<div class="green" data-v-f3edg9>hi</div> 
    </template> 
    
    <style> 
    	// 标签添加的自定义属性和postcss来对应
    	.green[data-v-f3edg9] { 
    		color: green; 
    	}
    </style>
    

    扩展1:

    如果我们很多组件都需要使用scss变量,那么怎么办呢,这个时候我们可以把公共的提出去。例如我们上面的$color: green变量给提出去。

    在src下新建一个styles文件夹,然后添加一个common.scss文件,把$color: green剪切到这个文件中。

    然后装style-resources-loader 插件。

    yarn add style-resources-loader
    

    然后在vue.config.js文件中,修改代码为:

    const path = require('path')
    
    function addStyleResource(rule) {
      rule.use('style-resource')
        .loader('style-resources-loader')
        .options({
          patterns: [
            path.resolve(__dirname, './src/styles/common.scss'),
          ],
        })
    }
    module.exports = { 
      publicPath: process.env.NODE_ENV === 'production'? '/部署服务器中的文件夹名/': '/',
      chainWebpack: config => {
        const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
        types.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)))
      }, 
    }
    

    然后再重新启动项目。

    在程序启动之初,先把这个文件加载了,然后其他文件就都可以使用了。

    扩展2:

    深度作用选择器: >>>

    在非css预处理器中,使用 >>> 操作符可以使 scoped 样式中的一个选择器能够作用得“更深”,例如影响

    子组件(必需要写在scoped 样式中)。

    <style scoped> 
    	#app >>> p { 
    		color: green 
    	}
    </style>
    

    在css预处理器无法正确解析 >>> 。我们使用 /deep/ 或 ::v-deep 操作符。

    <style scoped lang="scss"> 
    	 #app {
        // /deep/ p{
        //   color: green;
        // }
        ::v-deep p{
          color: green;
        }
      }
    </style>
    

    路由

    官方地址

    安装

    如果之前创建项目没有选择router,那么需要安装路由插件。

    vue add router
    
    基础使用

    在router/index.js,可以配置路由。

    const routes = [
      {
        path: '/',
        name: 'Home',
        component: Home
      },
      {
        path: '/about',
        name: 'About',
        // route level code-splitting
        // this generates a separate chunk (about.[hash].js) for this route
        // which is lazy-loaded when the route is visited.
        // 使用webpack+vue提供的异步组件的方式实现懒加载
        // 代码将来会分割出去成一个独立的chunk(分片的模式)
        // 只有进入到这个路由,才会实时的去下载这个组件,因为打包的时候是单独打包出去的,这样加载时间会变短
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
      }
    ]
    
    路由出口

    一般在App.vue中,使用路由的总出口 : <router-view></router-view>

    <template>
      <div id="app">
        <div id="nav">
          <router-link to="/">Home</router-link> |
          <router-link to="/about">About</router-link>
        </div>
    
        <!-- 路由的出口 -->
        <router-view/>
      </div>
    </template>
    
    动态路由匹配

    我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 Detail 组件,对于所有 ID 各不相同的商品,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:

    { path: '/detail/:id', component: Detail }
    
     // router/index.js中添加:
     {
        // :id标示动态路由
        path: '/detail/:id',
        name: 'Detail',
        component: () => import('../views/Detail.vue')
      },
    
    路由导航

    语法:<router-link :to='' />

    使用router-link可以进行路由导航,to是要导航到哪儿去,里面写的是路由的path。

    使用:

          <li v-for="item of goodsList" :key='item.id'>
            <router-link :to='`/detail/${item.id}`'>
              {{item.name}} - {{item.price | symbol("$")}}
            </router-link>
          </li>
    

    获取:

    <template>
      <div>
        <h1>商品详情页</h1>
        <p>{{$route.params.id}}</p>
      </div>
    </template>
    
    <script>
      export default {
      	// 响应路由参数变化
        // 如果不这样监听,那么在多个之间切换的时候,组件为了考虑性能,是不会进行销毁重建的,也就是说在下面mounted或者created都不会再触发
        watch: {
          $route: {
            immediate: true,
            // deep: true,
            handler() {
              console.log('通过id去获取详情');
              
            }
          }
        },
        mounted () {
          console.log(this.$route.params.id);
        },
         created () {
          console.log('发起请求');
        },
      }
    </script>
    
    通配符
    	{
        // 会匹配所有路径
        // 从上往下去匹配,当其他的都匹配不上,代表路由有误,这个时候就可以去加载我们写的404提示页面
        // 一般情况下,都会放到最后
        path: '*',
        component: () => import('../views/404.vue')
      }
    
    嵌套路由

    实际的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件。

    在路由对象中添加children属性,值是一个数组对象。

     {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue'),
        children: [
          {
            path: 'detail/:id',
            name: 'Detail',
            component: () => import('../views/Detail.vue')
          }
        ]
      },
    

    改造about页面添加嵌套路由出口:

    <template>
      <div class="about">
        <h1>about</h1>
        <ul>
          <li v-for="item of goodsList" :key='item.id'>
            <router-link :to='`/about/detail/${item.id}`'>
              {{item.name}} - {{item.price | symbol("$")}}
            </router-link>
          </li>
        </ul>
    
        <!-- 嵌套路由出口 -->
        <router-view></router-view>
      </div>
    </template>
    

    这个时候,(1)访问/detail/:id,就是单独的详情页面,(2)/about是商品列表,(3)/about/detail/:id是商品列表下还有商品详情。

    路由跳转

    语法:router.push(location, onComplete?, onAbort?)

    // 字符串 
    router.push('/') 
    // 对象 
    router.push({ path: `/about/detail/${item.id}` }) 
    // 命名的路由 
    router.push({ 
    	name: 'Detail', // 路由文件中,去匹配 我们书写的name值
    	params: { id: item.id } // 参数
    })
    // 带查询参数,最终会变成 /goods?price=100 
    router.push({ path: 'goods', query: { price: 100 }})
    
    路由懒加载

    路由组件的懒加载能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

    把组件按组分块:

    () => import(/* webpackChunkName: "group-about" */ "../views/About.vue")
    

    路由进阶

    路由守卫

    vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

    全局守卫
    router.beforeEach((to, from, next) => { 
    	xxx代码 
    	// to: Route: 即将要进入的目标 路由对象 
    	// from: Route: 当前导航正要离开的路由 
    	// next: Function: 一定要调用该方法来 resolve 这个钩子。 
    })
    

    在router/index.js中,添加

    // 全局守卫
    // to:到哪儿去 from:从哪儿来 next:放行
    router.beforeEach((to, from, next) => {
      // 判断路由是否需要守卫
      // meta数据
      if (to.meta.auth) {
        // 是否登录
        if (window.isLogin) { // 假如在全局保存了一个变量isLogin,用来判断是否登陆
          next() // 放行
        } else {
          next('/login?redirect='+to.fullPath) // 跳转到登陆,然后登陆成功之后重定向到想去的页面
        }
      } else {
        next()
      }
    })
    
    路由独享的守卫

    和全局守卫beforeEach参数是一致的。

    beforeEnter((to, from, next) => { 
    	xxx代码 
    	// to: Route: 即将要进入的目标 路由对象 
    	// from: Route: 当前导航正要离开的路由 
    	// next: Function: 一定要调用该方法来 resolve 这个钩子。 
    })
    

    例如:

     {
        path: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
        children: [
          {
            path: 'detail/:id',
            name: 'Detail',
            component: () => import('../views/Detail.vue')
          }
        ],
        beforeEnter(to, from, next) {
          // 是否登录
          if (window.isLogin) { // 假如在全局保存了一个变量isLogin,用来判断是否登陆
            next() // 放行
          } else {
            next('/login?redirect=' + to.fullPath) // 跳转到登陆,然后登陆成功之后重定向到想去的 页面
          }
        }
      },
    
    组件内守卫

    可以在路由组件内直接定义以下路由导航守卫(写在组件内的方法):

    • beforeRouteEnter

    • beforeRouteUpdate

    • beforeRouteLeave

    // About.vue 
    beforeRouteEnter(to, from, next) { 
    	if (window.isLogin) { 
    		next(); 
    	} else { 
    		next("/login?redirect=" + to.fullPath); 
    	} 
    }
    

    动态路由

    通过router.addRoutes(routes)方式动态添加路由

    例如很常见的要求用户必须登录,否则只能去登录页。

    修改全局守卫为:

    router.beforeEach((to, from, next) => {
      // 已登录
      if (window.isLogin) {
        if (to.path === '/login') {
          // 已登录没必要去登录页,重定向至首页
          next('/')
        } else {
          // 去其他页放行
          next()
        }
      } else {
        // 没有登录
        if (to.path === '/login') {
          // 要去登录页就直接放行
          next()
        } else {
          // 否则重定向到登录页
          next('/login?redirect=' + to.fullPath)
        }
      }
    })
    

    修改Login.vue,当用户登录成功后动态添加/about

    		login() {
          window.isLogin = true;
          // 注意参数需要是数组对象,如果没有登录,那么就不会有这个路由
          this.$router.addRoutes([{
            path: "/about",
            name: "About",
            // route level code-splitting
            // this generates a separate chunk (about.[hash].js) for this route
            // which is lazy-loaded when the route is visited.
            // 使用webpack+vue提供的异步组件的方式实现懒加载
            // 代码将来会分割出去成一个独立的chunk(分片的模式)
            // 只有进入到这个路由,才会实时的去下载这个组件,因为打包的时候是单独打包出去的,这样加载时间会变短
            component: () =>
              import(/* webpackChunkName: "about" */ "../views/About.vue"),
            children: [
              {
                path: "detail/:id",
                name: "Detail",
                component: () => import("../views/Detail.vue")
              }
            ],
            beforeEnter(to, from, next) {
              // 是否登录
              if (window.isLogin) {
                // 假如在全局保存了一个变量isLogin,用来判断是否登陆
                next(); // 放行
              } else {
                next("/login?redirect=" + to.fullPath); // 跳转到登陆,然后登陆成功之后重定向到想去的 页面
              }
            }
          }]);
          
           // 使用的是带查询参数,所以是获取query
          this.$router.push(this.$route.query.redirect);
        }
    

    然后,来思考一下,虽然做了权限认证,但是会遇到一个问题,当我刷新的时候,添加的路由没了,又要走登录流程,这个肯定是不合理的,那么怎么来解决呢?自己试一试呢。

    组件缓存

    keep-alive

    利用keepalive做组件缓存,保留组件状态,提高执行效率。

    例如:缓存about组件。

    在App.vue中,改造代码:

    		<!-- 缓存组件 -->
        <keep-alive include="about" max='5'>
        	<!-- 注意使用include或则exclude时,去匹配的是组件中的name值,不是路由中的name -->
        	<!-- include是要缓存的组件,exclude是不缓存的组件,如果是多个,name值之间逗号隔开,例如include="about,detail" -->
        	<!-- 属性max,是指需要缓存的最大数,如果超出了,就会把最老的缓存t出去,加上最新的缓存, 以达到资源的最优化 -->
          <router-view/>
        </keep-alive>
    

    由于keep-alive的出现,就有两个特别的钩子:activated、deactivated。

    在about组件中去监听:

      // 被keep-alive缓存会触发
      activated(){
        console.log('activated');
      },
      deactivated(){
        console.log('deactivated');
      },
    

    github代码地址

  • 相关阅读:
    【HEVC帧间预测论文】P1.8 Complexity Control of High Efficiency Video Encoders for Power-Constrained Devices
    【HEVC帧间预测论文】P1.7 Content Based Hierarchical Fast Coding Unit Decision Algorithm
    【HEVC帧间预测论文】P1.6 A Fast HEVC Inter CU Selection Method Based on Pyramid Motion Divergence
    【HEVC帧间预测论文】P1.5 Fast Coding Unit Size Selection for HEVC based on Bayesian Decision Rule
    【HEVC帧间预测论文】P1.4 Motion Vectors Merging: Low Complexity Prediction Unit Decision
    【HEVC帧间预测论文】P1.3 Fast Inter-Frame Prediction Algorithm of HEVC Based on Graphic Information
    【HEVC帧间预测论文】P1.2 An Efficient Inter Mode Decision Approach for H.264 Video Codin
    【HEVC帧间预测论文】P1.1 基于运动特征的HEVC快速帧间预测算法
    【HEVC简介】DB-DeBlock Filter
    【HEVC简介】ALF-Adative Loop Filter
  • 原文地址:https://www.cnblogs.com/zz-zrr/p/14438076.html
Copyright © 2020-2023  润新知