当前位置:首页 > 网站技术 > 前端技术 > 正文内容

Vue2.x进阶知识

binadmin2020-06-18前端技术92



1.自定义指令—directive指令用法

官方文档: https://cn.vuejs.org/v2/guide/custom-directive.html
Vue.directive("指令名称","对象")
在template里使用时:"v-name"
使用directive可以封装一个vue插件全局调用
例子:
   

<div class="app" v-sqyhtml="isLoading">
       <div >{{data}}</div>
       <button @click="update">更新</button>
   </div>
   <script>
       Vue.directive('sqyhtml',{
           update(el,binding,vnode){
               console.log(el,binding,vnode)
               if (binding.value) {
               const div = document.createElement('div')
               div.innerText = '加载中…'
               div.setAttribute('id', 'loading')
               div.style.position = 'absolute'
               div.style.left = 0
               div.style.top = 0
               div.style.width = '100%'
               div.style.height = '100%'
               div.style.display = 'flex'
               div.style.justifyContent = 'center'
               div.style.alignItems = 'center'
               div.style.color = 'white'
               div.style.background = 'rgba(0, 0, 0, .7)'
               document.body.append(div)
               } else {
               document.body.removeChild(document.getElementById('loading'))
               }
           }
       })
       new Vue({
          el:'.app',
          data(){
              return {
               isLoading:false,
               data:''
              }
          },
          methods:{
              update() {
                  this.isLoading = true
                  setTimeout(()=>{
                      this.data='用户数据'
                      this.isLoading = false
                  },3000)
              }
          }
       })
   </script>

2.Vue.extend 进阶用法

自定义一个VUE api以供全局调用。 
 

<div class="app">
      <button @click="showLoading">显示loading</button>
   </div>
   <script>
       function Loading(msg){
         const LoadingComponent = Vue.extend({
          name:'LoadingComponent',
          template:'<div id="loading-wrapper">{{msg}}</div>',
          props:{
              msg:{
                  type:String,
                  default:msg
              }
          }
         })
         const div = document.createElement("div")
         div.setAttribute("id","loading-wrapper")
         document.body.append(div)
         new LoadingComponent().$mount("#loading-wrapper")
         return () =>{
             document.body.removeChild(document.getElementById("loading-wrapper"))
         }
       }
       Vue.prototype.$loading = Loading
       new Vue({
          el:'.app',
          methods:{
              showLoading () {
                  const hide = this.$loading('正在加载,请稍等。。。。。')
                  setTimeout(() =>{
                    hide()
                  },3000)
              }
          }
       })
   </script>


注:$mount的用法是把定义的组件挂载到vue实例上

3.Vue.use引入自定义插件并使用

<div id="root">
     <button @click="showLoading">显示Loading</button>
   </div>
   <script>
     const loadingPlugin = {
       install: function(vm) {
         const LoadingComponent = vm.extend({
           template: '<div id="loading-wrapper">{{msg}}</div>',
           props: {
             msg: {
               type: String,
               default: 'loading…'
             }
           }
         }, 'LoadingComponent')
         function Loading(msg) {
           const div = document.createElement('div')
           div.setAttribute('id', 'loading-wrapper')
           document.body.append(div)
           new LoadingComponent({
             props: {
               msg: {
                 type: String,
                 default: msg
               }
             } 
           }).$mount('#loading-wrapper')
           return () => {
             document.body.removeChild(document.getElementById('loading-wrapper'))
           }
         }
         vm.prototype.$loading = Loading
       }
     }
     Vue.use(loadingPlugin)
     new Vue({
       el: '#root',
       methods: {
         showLoading() {
           const hide = this.$loading('正在加载,请稍等…')
           setTimeout(() => {
             hide()
           }, 2000)
         }
       }
     })
   </script>

4.组件通信 provide 和 inject

通过在父组件定义provide,将自身组件打包成一个属性,提供给子组件调用
在子组件inject数组调用父组件定义的属性。
直接通过属性实例直接调用父组件里面的方法
例子:
   

 <div class="app">
      <Test></Test>
   </div>
   <script>
       function registerPlugin(){
           Vue.component("Test",{
             template:"<div>{{message}}<Test2 /></div>",
             provide(){
               return {
                   elTest: this
               }
             },
             data(){
                 return {
                  message: '彬'
                 }
             },
             methods:{
                 change(component){
                     this.message = 'message form'+component
                 }
             }
           })
           Vue.component("Test2",{
               template:"<Test3 />"
           })
           Vue.component("Test3",{
               template:"<button @click='cheangeMessage'>chage</button>",
               inject:['elTest'],
               methods:{
                   cheangeMessage(){
                       this.elTest.change(this.$options._componentTag)
                   }
               }
           })
       }
       Vue.use(registerPlugin)
       new Vue({
          el:'.app',
       })
   </script>

5.过滤器filters

 <div class="app">
       {{message | lower}}
   </div>
   <script>
       new Vue({
          el:'.app',
          filters:{
              lower(value){
                  return value.toLowerCase()
              }
          },
          data(){
              return {
               message:'HELLO WORD'
              }
              
          },
       })
   </script>

6.VUE2.6特性—observable

一定要在实例的计算属性中调用observable定义的值

  

  <div class="app">
       {{message}}
       <button @click="change">change 事件</button>
   </div>
   <script>
       const state = Vue.observable({message:'Vue 2.6.0'})
       const mutation = {
           setMessage(value){
               state.message = value
           }
       }
       new Vue({
          el:'.app',
          computed: {
              message(){
                  return state.message
              }
          },
          methods:{
              change(){
                  mutation.setMessage('Vue 3.0')
              }
          }
       })
   </script>

7.VUE2.6特新–插槽slot用法

 <div class="app">
      <div>案例1:slot的基本用法</div>
      <Test>
         <template v-slot:header='{user}'>
           <div>自定义header({{user.a}})</div>
         </template>
         <template v-slot="{user}">
           <div>自定义body({{user.b}})</div>
         </template>
      </Test>
   </div>
   <div class="app2">
       <div>案例2:Vue2.6新特性 – 动态slot</div>
       <Test>
           <template v-slot:[section]='{section}'>
               <div>this is {{section}}</div>
           </template>
       </Test>
       <button @click="change">切换header和body</button>
   </div>
   <script>
       Vue.component("Test",{
          template: `<div>
                       <slot name='header' :user='obj' section='header'>
                         <div>默认 header</div>
                       </slot>
                       <slot :user='obj' section='body'>默认 body</slot>
                    </div>`,
         data() {
             return {
                 obj:{a:1,b:2}
             }
         }
       })
       new Vue({el:'.app'})
       new Vue({
           el:'.app2',
           data(){
               return {
                   section:'header'
               }
           },
           methods:{
               change(){
                   this.section ==='header'? this.section ='default':this.section ='header'
               }
           }
       })
   </script>


注:v-slot可以简写"#"

8.Element-ui的按需加载

对 element-ui 进行全量打包的结果,按需加载的用法如下:
安装 babel-plugin-component
npm install babel-plugin-component -D 
修改 babel.config.js:
plugins:[
   [
     'component',
     {
       libraryName: "element-ui",
       styleLibraryName: "theme-chalk"
     }
   ]
 ] 
按需引入 Button 和 Message
import {Button, Message} from 'element-ui'
Vue.component(Button.name, Button)
Vue.prototype.$message = Message 

插件引用
可以通过 element 插件快速集成 element-ui
vue add element

9.element-ui表单校验基本用法

在data里面定义校验规则
 data() {
   const userValidator =(rule,value,callback)=>{
      if(value.length>3){
        callback()
      }else {
        callback(new Error('用户名长度必须大于3'))
      }
   }
   return {
     data: {
       user: ' ',
       region: "
     },
     rules:{
       user:[
         {required:true,trigger:'change',message:'用户名必须输入'},
         {validator:userValidator,trigger:'change'} 
       ]
     }
   }
 }, 
注:需要在<el-form>加上  :rules="rules" ,在需要校验的<el-form-item>加上 prop="user"
在data里面定义的rules校验是在"change"时,还需要在点击提交的时候验证信息
methods: {
   /* eslint-disable */
   onSubmit() {
     console.log(this.data)
     this.$refs.form.validate((isValid,errors)=>{
       console.log(isValid,errors)
     })
   }
 }

10.element-ui表单校验高级用法

1.动态的添加校验规则(把第九点的基本用法data里的方法统一用事件来表达)
在template里添加一个click事件,绑定addRolu
 

addRule() {
     const userValidator = (rule, value, callback) => {
       if (value.length > 3) {
         this.inputError = "
         this.inputValidateStatus = "
         callback()
       } else {
         callback(new Error('用户名长度必须大于3'))
       }
     }
     const newRule = [
       …this.rules.user,
       { validator: userValidator, trigger: 'change' }
     ]
     this.rules = Object.assign({}, this.rules, { user: newRule })
  } 
注:在动态添加时,会马上校验规则,可以在<el-form>加一个属性" validate-on-rule-change "
令 
:validate-on-rule-change='false'
就不会马上校验,



2.手动控制校验状态

设置<el-from-item>属性 validate-status 和 error
validate-status:验证状态,枚举值,共四种:
  success:验证成功
  error:验证失败
  validating:验证中
  (空):未验证
error:自定义错误提示 
在data里 

error:",
status:",

然后定义三个点击事件,通过三个按钮去分别实现验证成功、验证失败、验证中三种状态
 showError() {
   this.status = 'error'
   this.error = '用户名输入有误'
 },
 showSuccess() {
   this.status = 'success'
   this.error = "
 },
 showValidating() {
   this.status = 'validating'
   this.error = "
 }

11.vue-router的使用方法

 vue-router的基本使用方法 
1.安装vue-router依赖
 
npm i -S vue-router 

2.使用vue-router插件
 
import Route from 'vue-router'
 Vue.use(Route)

3.初始化vue-router对象
const routes = [
 { path: '/a', component: A },
 { path: '/b', component: B },
 { path: '/hello-world', component: HelloWorld }
]
const router = new Route({
 routes
})
注:这里省略了定义A组件和B组件的过程,这两个组件与普通组件无异

4.实例化Vue对象,传入router参数

new Vue({
 router,
 render: h => h(App)
})
5.使用router-view和router-link
router-view和router-link是vue-router官方提供的两个组件,
router-view会替换为路由对应的组件,router-link相当于a标签,
点击后会加载to属性中路由对应的组件

<div>
 <div>
   <router-link to="/a">a</router-link>
 </div>
 <div>
   <router-link to="/b">b</router-link>
 </div>
 <div>
   <router-link to="/hello-world">hello-world</router-link>
 </div>
</div>
<router-view />

路由嵌套

上面是一个非常简单的vue-router case,
实际项目开发过程中,需求往往不会这么简单,
比如我们希望实现/a/aa路由,并且/aa对应的组件嵌套在/a之下,
这时我们需要修改路由的配置文件:

const routes = [{
 path: '/a',
 component: A,
 redirect: '/a/aa',
 children: [
   { 
     path: '/a/aa',
     component: AA,
   }] 
}]
并修改A组件的内容:

<template>
 <div>
   <div>a</div>
   <router-view />
 </div>
</template>
由于A组件是父级路由,所以也需要添加router-view组件,动态匹配子路由

重定向
将一个路由重定向到另一个路由,实际开发过程中非常实用,修改配置文件即可:

const routes = [{
   path: '/a',
   component: A,
   redirect: '/a/aa',
   children: [{
     path: '/a/aa',
     component: AA,
   }] 
 }]

动态路由

为了支持restful形式路由以及更复杂的场景时,我们可以使用动态路由,
定义路由时,在路由前加上冒号即可,我们先添加AA2组件,
动态路由部分通过this.$route.params进行接收:


<template>
 <div>
   aa2
   <div>{{id}}</div>
 </div>
</template>

<script>
 export default {
   data() {
     return {
       id: null
     }
   },
   created() {
     this.id = this.$route.params.id
   }
 }
</script>
修改路由配置后生效:

const routes = [
 {
   path: '/a',
   component: A,
   redirect: '/a/aa',
   children: [
     {
       path: '/a/aa',
       component: AA,
     },
     {
       path: '/a/:id',
       component: AA2,
     },
   ]
 }
]
动态路由的优先级低于普通路由,
所以我们访问/a/aa时会匹配到AA组件,而输入其他路由时会匹配到AA2组件

路由参数
参数传递是我们开发过程中必不可少的步骤,vue-router支持参数传递,
通过this.$route.query进行接收,我们修改AA组件进行测试

<template>
 <div>
   aa
   <div>{{message}}</div>
 </div>
</template>

<script>
 export default {
   data() {
     return {
       message: "
     }
   },
   created() {
     this.message = this.$route.query.message || "
   }
 }
</script>

编程式路由

有很多时候我们需要手动操作路由的跳转,
这时我们需要使用this.$router,以下是一些常用的操作:

路由跳转
this.$router.push('/a/aa')

带参数路由跳转
this.$router.push({
 path: '/a/aa',
 query: {
   message: 'hello'
 }
})

不向history插入记录
this.$router.replace('/a/123')

回退

this.$router.go(-1)


12.vuex原理解析

 

   <div class="app">
    {{data}}
  </div>
  <div class="app2">
   {{data}}
  </div>
  <div class="app3">
     <button @click='change'>change</button>
     </div>
  <script>
      function registerPlugin(Vue){
          // 模拟vue中的vuex,是对象
          const vuex={}
          // _vm是一个实例 状态管理核心
          vuex._vm =new Vue({
              data:{
                message:'hello vue.js'
              }
          })
          // vuex.state对象
          vuex.state = vuex._vm
          vuex.mutations= {
              setMassage(value){
                  vuex.state.message =value
              }
          }
          function init(){
              this.$store =vuex
          }
          // 全局调用,在所有实例时beforeCreate时候调用init
          Vue.mixin({
              beforeCreate:init
          })
      }
      Vue.use(registerPlugin)
      
     new Vue({
         el:'.app',
         computed:{
             data(){
                 return this.$store.state.message
             }
         }
     })
     new Vue({
         el:'.app2',
         computed:{
             data(){
                 return this.$store.state.message
             }
         }
     })
     new Vue({
         el:'.app3',
         methods:{
             change(){
                  const newValue = this.$store.state.message+'.'
                  this.$store.mutations.setMassage(newValue)
             }
         }
     })
  </script>

 


标签: vueecmascript6
分享给朋友:

相关文章

使用rem做手机端网页自适应

使用rem做手机端网页自适应

利用原生js做手机端网页自适应解决方案rem布局刚开始我用的是下面这段代码,然后js通过外部链接引入,最后每次用手机刷新网页的时候都会出现缩略图function getRem(pwidth,...

前端日常编程代码便捷汇总

前端日常编程代码便捷汇总

1、使用form表单进行上传文件需要为form添加enctype="multipart/form-data" 属性,除此之外还需要将表单的提交方法改成post,如下 me...

基于Vue自定义左右渐变图片轮播组件

基于Vue自定义左右渐变图片轮播组件

本文取自 https://github.com/zhangxiaoshang/va-carousel 的 一个基于 vue 的图片轮播组件 我在此基础上修改了一下,自己用...

在nuxt中使用localStorage

在nuxt中使用localStorage

摘至: https://zhuanlan.zhihu.com/p/82481387使用 localStorage 进行缓存,操作比 cookie 更简单,且存储空间更大,用 vue.js 使...

Vue2.x基础知识

Vue2.x基础知识

1.vue绑定值与字符串拼接四种方法 A  :title="`字符串${变量}`"    B  :titl...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

分享:

支付宝

微信