分类
vue

4.VUE进阶和Elment-ui入门

  • 前端:Vue+Element-UI+Vue-element-admin
  • 后端:Node+Express+MySql

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>

“4.VUE进阶和Elment-ui入门”上的1条回复

[…] 在子组件定义数据,在父组件决定显示哪些数据,通过子组件的slot附加属性传到父组件里 <div class=”app”>       <child>            <template slot-scope=”props”>                   <h2>{{props.nameU}}–{{props.content}}–{{props.index}}</h2>           </template>       </child>    </div>    <script>        Vue.component(“child”,{            data:function(){                return {                   list:[                       {name:’one’,content:1},                       {name:’two’,content:’gf’},                       {name:’three’,content:3},                       {name:’four’,content:4},                       {name:’five’,content:5},                       {name:’six’,content:6},]                  }            },            // 不能用name            template:`<div>                        <slot v-for=”(item,index) of list” :index=index :nameU=item.name :content=item.content></slot>                      </div>`        })        var vm= new Vue({           el:’.app’,           data:{           },        })    </script> slot-scope的值要和父组件调用的一致,父组件调用的属性由子组件’slot’属性决定作用域插槽必须以’template’开头和结尾作用域插槽接收到的数据以’h2’模板显示注:在vue2.6版本里,统一使用v-slot(见4.Vue Element+Node.js开发企业通用管理后台系统) […]

发表评论

电子邮件地址不会被公开。 必填项已用*标注