vue笔记

vue笔记

一.vue实例

vue的生命周期

  • beforeCreate(创建前),

  • created(创建后),

  • beforeMount(载入前),

  • mounted(载入后),

  • beforeUpdate(更新前),

  • updated(更新后),

  • beforeDestroy(销毁前),

  • destroyed(销毁后)

  • (1).beforeCreae(){}

  • (2).created(){}

  • (3).beforMount(){}

  • (4).mounted(){}

    mounted: function () {
    this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
    })
    }

  • (5).beforeUpdate(){}

  • (6).updated(){}

  • (7).不常用周期 activated deactivated beforeDestroy destroyed(Vue 实例销毁后调用) errorCaptured

二.模板语法

1.插值(是vue实例data里面的数据才能同步到页面展示)

  • (1).文本
    {{msg}}
    v-text="msg"

    v-model='msg'

    <input type="checkbox" id="checkbox" v-model="checked">

    <div id='example-3'>
    <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
    <label for="jack">Jack</label>
    <input type="checkbox" id="john" value="John" v-model="checkedNames">
    <label for="john">John</label>
    <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
    <label for="mike">Mike</label>


    <span>Checked names: {{ checkedNames }}</span>
    </div>

    <div id="example-4">
    <input type="radio" id="one" value="One" v-model="picked">
    <label for="one">One</label>


    <input type="radio" id="two" value="Two" v-model="picked">
    <label for="two">Two</label>


    <span>Picked: {{ picked }}</span>
    </div>
    new Vue({
    el: '#example-4',
    data: {
    picked: ''
    }
    })

    <div id="example-5">
    <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
    </select>
    <span>Selected: {{ selected }}</span>
    </div>
    new Vue({
    el: '...',
    data: {
    selected: ''
    }
    })
  • (2).原始HTML(后台渲染的数据通过这种方法插入html,css如果包含scoped则会样式失效)
    v-html="msg"
  • (3).特性(Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 v-bind 指令:用于一些属性的绑定)
    :disabled="msg"
    :href="url"
  • (4).使用js
    {{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }}
    {{ message.split('').reverse().join('') }}

2.指令

  •   @click="getInfo()"
    

3.修饰符

  • (1).lazy
    <input v-model.lazy="msg" >
  • (2).number
    <input v-model.number="age" type="number">
  • (3).trim
    <input v-model.trim="msg">

4. 数组的变异方法(mutation method,会改变被这些方法调用的原始数组)会触发视图更新,有以下七个

  • push()/pop()/shift()/unshift()/splice()/sort()/reverse()

三.计算属性和侦听器

1.计算属性

  • 对于任何复杂逻辑,你都应当使用计算属性(计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。可以监听多个值从而改变)
    var vm = new Vue({
    el: '#example',
    data: {
    message: 'Hello'
    },
    computed: {
    // 计算属性的 getter
    reversedMessage: function () {
    // 'this' 指向 vm 实例
    return this.message.split('').reverse().join('')
    }
    }
    })
    computed: {
    fullName: {
    // getter
    get: function () {
    return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
    var names = newValue.split(' ')
    this.firstName = names[0]
    this.lastName = names[names.length - 1]
    }
    }
    }

2.侦听属性

    watch: {
         firstName: function (val) {
           this.fullName = val + ' ' + this.lastName
         },
         lastName: function (val) {
           this.fullName = this.firstName + ' ' + val
         }
       }

四.class与Style绑定

  • 1.calss动态绑定(isActive取布尔值)
    :class="{className:isActive}"
    :class="{className:isActive,className1:isActive1}"
    :class="classObject"
    data: {
    classObject: {
    active: true,
    'text-danger': false
    }
    }
    :class="[activeClass, errorClass]"
    :class="[isActive ? activeClass : '', errorClass]"
    :class="[{ active: isActive }, errorClass]"
  • 2:style(样式的动态绑定,vue会自动添加浏览器兼容属性前缀)
    :style="{ color: activeColor, fontSize: fontSize + 'px' }"
    :style="styleObject"
    data: {
    styleObject: {
    color: 'red',
    fontSize: '13px'
    }
    }

五.条件渲染

  • 1.v-if v-else v-else-if 和js的if判断类似

      <h1 v-if="type==A">Yes</h1>
      <h1 v-else-if="type==B">No</h1>
      <h1 v-else>Not A/B</h1>
    
  • 2.key(Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染,如果复用它们就加key给元素添加唯一标识)

  • 3.v-show (v-show 不支持 template 元素,也不支持 v-else)

      <h1 v-show="ok">Hello!</h1>
    
  • 4.v-if和v-show的区别

    • v-if是真正的条件渲染会适当地被销毁和重建而v-show不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

六.列表渲染

  • 1.v-for 指令根据一组数组的选项列表进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名()可以随便定义。
    <ul> <li v-for="item in items" :key='item.id'> {{ item.message }} </li> </ul> <ul> <li v-for="(item,index) in items" :key='item.id'> {{index+'.'+ item.message }} </li> </ul>

七.事件处理

  • 1.写法
    @click="counter += 1"
    @:click="greet"
    @:click="greet(id,name)"
    @:click="greet($event)"

  • 2.事件修饰符

      <!-- 阻止单击事件继续传播 -->
      <a v-on:click.stop="doThis"></a>
      <!-- 提交事件不再重载页面 -->
      <form v-on:submit.prevent="onSubmit"></form>
    
      <!-- 修饰符可以串联 -->
      <a v-on:click.stop.prevent="doThat"></a>
    
      <!-- 只有修饰符 -->
      <form v-on:submit.prevent></form>
    
      <!-- 添加事件监听器时使用事件捕获模式 -->
      <!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
      <div v-on:click.capture="doThis">...</div>
    
      <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
      <!-- 即事件不是从内部元素触发的 -->
      <div v-on:click.self="doThat">...</div>
      <!-- 点击事件将只会触发一次 -->
      <a v-on:click.once="doThis"></a>
      <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
      <!-- 而不会等待 `onScroll` 完成  -->
      <!-- 这其中包含 `event.preventDefault()` 的情况 -->
      <div v-on:scroll.passive="onScroll">...</div>
      <!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
      <input v-on:keyup.13="submit">
      <!-- 同上 -->
      <input v-on:keyup.enter="submit">
    
      <!-- 缩写语法 -->
      <input @keyup.enter="submit">
    

八.组件

  • 1.父组件向子组件传值
    • 1.子组件
      <template> <div> <h2>子组件Child</h2> <p>{{ msg }}</p> </div> </template> <script> export default{ props:['msg'] } </script>
    • 2.父组件
      <template> <div id="app"> <child msg = "hello vue"> </child> </div> </template> <script> import child from './components/Child' export default{ name:'app', components:{ child } } </script>
  • 2.子组件向父组件传值
    • 1.父组件
      <template> <div id="app"> <h2>父组件Child</h2> <child msg="hello vue" v-on:listenChildEvent="showMsg"></child> </div> </template> <script> export default{ name:'app', methods:{ showMsg:function(data){ alert(data); } } } </script>
    • 2.子组件
      <template> <div> <h2>子组件Child</h2> <p>{{ msg }}</p> <button v-on:click="sendMsgToParent"></button> </div> </template> <script> export default{ props:['msg'], methods:{ sendMsgToParent:function(){ this.$emit('listenChildEvent','this msg from child'); } } } </script>
  • 3.插槽(将自定义的内容插入到子组件中)

    <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>

    <base-layout> <template slot="header"> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template slot="footer"> <p>Here's some contact info</p> </template> </base-layout>

九.过渡动画

  • 1.过渡的类名
    • (1)v-enter 定义进入过渡的开始状态
    • (2)v-enter-active 定义过渡的状态
    • (3)v-enter-to 定义进入过渡的结束状态。
    • (4)v-leave 定义离开过渡的开始状态。
    • (5)v-leave-active 定义过渡的状态。
    • (6)v-leave-to 定义离开过渡的结束状态
     `<transition name="fade">
        <p v-if="show">hello</p>
      </transition>
      .fade-enter-active, .fade-leave-active {
        transition: opacity .5s;
      }
      .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
        opacity: 0;
      }`
  • 2.显性的过渡持续时间
    <transition :duration="1000">...</transition> <transition :duration="{ enter: 500, leave: 800 }">...</transition>

  • 3.JavaScript 钩子 (当只用 JavaScript 过渡的时候, 在 enter 和 leave 中,回调函数 done 是必须的 。否则,它们会被同步调用,过渡会立即完成。)
    <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter" v-on:enter-cancelled="enterCancelled" v-on:before-leave="beforeLeave" v-on:leave="leave" v-on:after-leave="afterLeave" v-on:leave-cancelled="leaveCancelled" > </transition>

  • 4.过渡模式

    • (1) in-out:新元素先进行过渡,完成之后当前元素过渡离开。
    • (2) out-in:当前元素先进行过渡,完成之后新元素过渡进入。

十.可复用性 & 组合

1.混入

  • 混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。同名钩子函数将混合为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用

      var mixin = {
                data: function () {
                  return {
                    message: 'hello',
                    foo: 'abc'
                  }
                }
           }
            new Vue({
                mixins: [mixin],
                data: function () {
                  return {
                    message: 'goodbye',
                    bar: 'def'
                  }
                },
                created: function () {
                  console.log(this.$data)
                  // => { message: "goodbye", foo: "abc", bar: "def" }
                }
           })
    
  • 全局混入

    • 也可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。
      // 为自定义的选项 'myOption' 注入一个处理器。
      Vue.mixin({
      created: function () {
      var myOption = this.$options.myOption
      if (myOption) {
      console.log(myOption)
      }
      }
      })
      new Vue({
      myOption: 'hello!'
      })
      // => "hello!"
  • 2.自定义指令

    • (1)示例
      // 注册一个全局自定义指令 v-focus
      Vue.directive('focus', {
      // 当被绑定的元素插入到 DOM 中时……
      inserted: function (el) {
      // 聚焦元素
      el.focus()
      }
      })
      //如果想注册局部指令
      directives: {
      focus: {
      // 指令的定义
      inserted: function (el) {
      el.focus()
      }
      }
      }
      <input v-focus>
    • (2)钩子函数
      • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
      • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
      • update:所在组件的 VNode 更新时调用
      • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
      • unbind:只调用一次,指令与元素解绑时调用。
    • (3)钩子函数参数
      • 除了 el 之外,其它参数都应该是只读的
      • el:指令所绑定的元素,可以用来直接操作 DOM 。
        binding:一个对象,包含以下属性:
      • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
      • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
        Vue.directive('demo', {
        bind: function (el, binding, vnode) {
        var s = JSON.stringify
        el.innerHTML =
        'name: ' + s(binding.name) + '
        ' +
        'value: ' + s(binding.value) + '
        ' +
        'expression: ' + s(binding.expression) + '
        ' +
        'argument: ' + s(binding.arg) + '
        ' +
        'modifiers: ' + s(binding.modifiers) + '
        ' +
        'vnode keys: ' + Object.keys(vnode).join(', ')
        }
        })
        new Vue({
        el: '#hook-arguments-example',
        data: {
        message: 'hello!'
        }
        })
  • 3.渲染函数
    +运用render函数
    Vue.component('anchored-heading', {
    render: function (createElement) {
    return createElement(
    'h' + this.level, // tag name 标签名称
    this.$slots.default // 子组件中的阵列
    )
    },
    props: {
    level: {
    type: Number,
    required: true
    }
    }
    })

  • 4.插件的引入和调用
    // 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
    var Vue = require('vue')
    var VueRouter = require('vue-router')

              // 不要忘了调用此方法
              Vue.use(VueRouter)
    
  • 5.过滤器(格式:双花括号插值和 v-bind 表达式 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:)

    {{ message | capitalize }}

      <!-- 在 `v-bind` 中 -->
      <div v-bind:id="rawId | formatId"></div>
    
    • 定义过滤器
      • 过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,capitalize 过滤器函数将会收到 message 的值作为第一个参数。

          <!-- 组件内定义 -->
          filters: {
            capitalize: function (value) {
              if (!value) return ''
              value = value.toString()
              return value.charAt(0).toUpperCase() + value.slice(1)
            }
          }
          <!-- 全局定义 -->
          Vue.filter('capitalize', function (value) {
            if (!value) return ''
            value = value.toString()
            return value.charAt(0).toUpperCase() + value.slice(1)
          })
          new Vue({
            // ...
          })
        

十一.路由系统(vue-router)

1.安装,引入

  • npm install vue-router

  • 入口文件中引入路由配置
    import router from './router'
    new Vue({
    el: '#app',
    router, // 使用路由对象实例
    store, // 使用vuex对象实例
    template: '<App/>',
    components: {App}
    })

  • 路由配置文件

    import Vue from 'vue'
    import Router from 'vue-router'

    import index from '../components/index'

    Vue.use(Router)

    export default new Router({
    routes: [

    {path: "/", redirect: "/index"},

    {path: "/index",name:'index', component: index},

    {
    path: "/user", component: index,
    children:[
    path: 'one', component: UserHome },
    path: 'two', component: UserHome }
    ]
    },

    {
    path: '/',
    components: {
    default: Foo,
    a: Bar,
    b: Baz
    }
    },

    { path: '/a', redirect: '/b' },
    { path: '/a', redirect: { name: 'foo' }},
    { path: '/a', redirect: to => {
    // 方法接收 目标路由 作为参数
    // return 重定向的 字符串路径/路径对象
    }},
    ]
    });

  • 2.跳转写法

      `<!-- 路由占位符 -->
      <router-view></router-view>
      <!-- 路径跳转 -->
      <router-link to='/index'></router-link>
      <!-- name跳转 -->
      <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>`
    
      <!--  push中使用path时params会被忽略-->
      this.$router.push({name:'/index',params: { userId: 123 }}})
      <!-- 等价于上面 -->
      router.push({ path: `/user/${userId}` })
      this.$router.push({path:'/index',query: { userId: 123 }}})
      <!-- router.replace用法和push一样,但是他不会向history添加记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。 -->
      <!-- router.go(n)参数是一个整数,意思是在 history 记录中向前或者后退多少步 -->
      <!-- 设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。 -->
      <router-link :to="{ path: '/abc'}" replace></router-link>
      <!-- 设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b -->
      <router-link :to="{ path: 'relative/path'}" append></router-link>
      <!-- 有时候想要 <router-link> 渲染成某种标签,例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。 -->
      <router-link to="/foo" tag="li">foo</router-link>
      <!-- 渲染结果 -->
      <li>foo</li>
    
  • 3.路由传参


      1. { path: '/user/:id', component: User }

        this.$route.params.id`

      1. const User = {
        props: ['id'],
        template: '<div>User {{ id }}</div>'
        }

        const router = new VueRouter({
        routes: [
        { path: '/user/:id', component: User, props: true },

               // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
               {
                 path: '/user/:id',
                 components: { default: User, sidebar: Sidebar },
                 props: { default: true, sidebar: false }
               }
             ]
           })
           <!-- 布尔模式 -->
           <!-- 如果 props 被设置为 true,route.params 将会被设置为组件属性 -->
           <!-- 对象模式 -->
           const router = new VueRouter({
             routes: [
               { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
             ]
           })
           <!-- 函数模式 -->
           const router = new VueRouter({
             routes: [
               { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
             ]
           })
        
  • 4.HTML5 History 模式
    +这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。(需要后台配置支持)
    const router = new VueRouter({
    mode: 'history',
    routes: [...]
    })

  • 5.路由检测

    watch: {
    '$route' (to, from) {
    // 对路由变化作出响应...
    }
    }

    beforeRouteUpdate (to, from, next) {

             next(vm=>{
                    console.log(44444);
                    vm.num=19;
                  })
          }
        }
    
  • 6.路由的滚动行为
    scrollBehavior (to, from, savedPosition) {
    return { x: 0, y: 0 }
    }

    scrollBehavior (to, from, savedPosition) {
    if (to.hash) {
    return {
    selector: to.hash
    }
    }
    }

十二.状态管理(vuex)

  • 1.Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。(在所有组件都可以调用)

    • 1.npm install vuex --save
      1. main.js
        *import store from './vuex/index'
      1. vuex/index
      • import Vue from 'vue'; import Vuex from 'vuex'; import mutations from './mutations'; import actions from './action'; import getters from './getters'; Vue.use(Vuex); const state = { count:123, title:'', routs:'', info:{name:'高级用户',phone:'1592****004'}, //个人信息 keyzt:false, //是否打开键盘输入 popUps:false, //是否打开弹窗 routersArr:[1,2,3], //设置进入页面的数组 saoyisao:true } export default new Vuex.Store({ state, getters, actions, mutations, })
  • 2.State (每个应用将仅仅包含一个 store 实例)

    • (1).在vue组件获取state对象里面的属性(可以直接赋值)

        this.$store.state.count
        <!-- 一般在计算属性中检测state -->
        computed: {
            count () {
              return this.$store.state.count
            }
      
    1. getter (可以认为是 store 的计算属性,Getter 接受 state 作为其第一个参数)


      getters: {
      doneTodos: state => {
      return state.todos.filter(todo => todo.done)
      }
      }

      this.$store.getters.doneTodos

    1. Mutation (Vuex 中的 mutation 非常类似于事件,Mutation 接受 state 作为其第一个参数)


      mutations: {
      increment (state) {
      // 变更状态
      state.count++
      }
      }

      this.$store.commit('increment')

    1. Action (Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作)
      • 和mutations主要区别就是异步

          mutations: {
              increment (state) {
                state.count++
              }
            },
            actions: {
              increment (context) {
                context.commit('increment')
              }
            }
            <!-- 触发 -->
          this.$store.dispatch('increment')
        
    1. Module (由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:)

         `const moduleA = {
             state: { ... },
             mutations: { ... },
             actions: { ... },
             getters: { ... }
         }
         const moduleB = {
             state: { ... },
             mutations: { ... },
             actions: { ... }
             }
         const store = new Vuex.Store({
             modules: {
                 a: moduleA,
                 b: moduleB
             }
         })
         store.state.a // -> moduleA 的状态
         store.state.b // -> moduleB 的状态`
      

十三.axios (请求后台接口插件)

  • 1.安装和配置
    • (1). $ npm install axios

    • (2). main.js中配置全局
      import axios from 'axios'
      Vue.prototype.axios = axios; Vue.prototype.axios.defaults.withCredentials = true;

    • (3). 组件中调用axios

        this.$axios.post(url, data).then(function (response) {
                    <!-- 请求成功 -->
                  if (response.data.error != 0) {
                  } else if (response.data.error == 0) {
                  }
                }).catch(function (error) {
                    <!-- 请求失败 -->
                      console.log(error);
                    });
      

十四.服务器端渲染

  • 1.安装引入
    • npm install vue vue-server-renderer --save
      / 第 1 步:创建一个 Vue 实例
      const Vue = require('vue')
      const app = new Vue({
      template: <div>Hello World</div>
      })
      // 第 2 步:创建一个 renderer
      const renderer = require('vue-server-renderer').createRenderer()
      // 第 3 步:将 Vue 实例渲染为 HTML
      renderer.renderToString(app, (err, html) => {
      if (err) throw err
      console.log(html)
      // => <div data-server-rendered="true">Hello World</div>
      })

十五.vue项目遇到的一些问题

服务端渲染 多页面

  • 1.vue打包后css前缀的丢失
    + optimize-css-assets-webpack-plugin 与 autoprefixer 之间互相冲突
    + 注释webpack.prod.conf.js里面的
    new OptimizeCSSPlugin({
    cssProcessorOptions: config.build.productionSourceMap
    ? { safe: true, map: { inline: false } }
    : { safe: true }
    }),
  • 2.打包app的安卓机物理返回键处理(在引入h5+里面的js的时候回失效)

    backs(){/安卓手机返回键处理/
    var that = this
    document.addEventListener('plusready', function () {
    var webview = plus.webview.currentWebview();
    var first = null;
    plus.key.addEventListener('backbutton', function () {
    webview.canBack(function (e) {
    if (!first) {
    first = new Date().getTime();//记录第一次按下回退键的时间
    webview.back();
    setTimeout(function () {//1s中后清除
    first = null;
    }, 1000);
    } else {
    if (new Date().getTime() - first < 1000) {//如果两次按下的时间小于1s,
    that.$MessageBox.confirm('确定退出吗?', '提示').then(action => {
    plus.runtime.quit();//那么就退出app
    }
    ).catch(() => {
    });
    }
    }
    }
    )
    })
    ;
    })
    ;
    }

    plus.key.addEventListener('backbutton', function() {
    var topWebview = plus.webview.getTopWebview();
    if(topWebview.id !== plus.runtime.appid) {
    topWebview.close('slide-out-right');
    } else {
    plus.nativeUI.confirm('是否退出应用', function(event) {
    var index = event.index;
    if(index === 1) {
    plus.runtime.quit();
    }
    }, '退出', ['取消', '确认']);
    }
    });
    3.火狐和ie的图片储存方式不同,(在验证码的url后面带上时间参数)

4.H5app扫一扫功能实现(调用H5的plus方法)

  •           `seac(){
              //创建扫描控件
                          startRecognize() {
                          let that = this;
                          if (!window.plus) return;
                          scan = new plus.barcode.Barcode('bcid');
                          scan.onmarked = onmarked;
                                  function onmarked(type, result, file) {
                                    switch (type) {
                                      case plus.barcode.QR:
                                        type = 'QR';
                                        break;
                                      case plus.barcode.EAN13:
                                        type = 'EAN13';
                                        break;
                                      case plus.barcode.EAN8:
                                        type = 'EAN8';
                                        break;
                                      default:
                                        type = '其它' + type;
                                        break;
                                    }
                                    //扫描完成操作
                                    result = result.replace(/\n/g, '');
                                    if (result.substring(0, 4) != 'http') {
                                      var str = result.split('#')[1]
                                      var arr = str.split('?')
                                      var path = arr[0]
                                      var arr1 = arr[1].split('=')
                                      that.$router.push({path: path, query: {number: arr1[1]}})
                                      that.closeScan();
                                    } else {
                                      if (result.split('#')[0] == that.url) {
                                        var str = result.split('#')[1]
                                        var arr = str.split('?')
                                        var path = arr[0]
                                        var arr1 = arr[1].split('=')
                                        that.$router.push({path: path, query: {number: arr1[1]}})
                                        that.closeScan();
                                      } else {
                                        that.$router.push({path: '/scanurl', query: {url: result}})
                                        that.closeScan();
                                      }
                                    }
                                  }
                                },
                                //开始扫描
                                startScan() {
                                  if (!window.plus) return;
                                  scan.start();
                                },
                                //关闭扫描
                                cancelScan() {
                                  if (!window.plus) return;
                                  scan.cancel();
                                },
                                //关闭条码识别控件
                                closeScan() {
                                  if (!window.plus) return;
                                  scan.close();
                                },
                                returnGo(){
                                  this.closeScan()
                                  this.$router.go(-1)
                                }
                                /* // 从相册中选择二维码图片
                                 scanPicture(){
                                 plus.gallery.pick(function (path) {
                                 plus.barcode.scan(path, onmarked, function (error) {
                                 plus.nativeUI.alert('无法识别此图片');
                                 });
                                 }, function (err) {
                                 console.log('Failed: ' + err.message);
                                 });
                                 },
                                 //返回上一页
                                 goIndex() {
                                 if (!window.plus) return;
                                 scan.close();
                                 this.$router.go(-1)
                                 },*/
              }`
    
  • 5.关于app状态栏颜色修改的问题

    • 1.在manifest.json->plus节点下加:

      "statusbar": {
      "immersed": true,
      "background": "#D74B28"
      },

      "launchwebview": {
      "statusbar": {
      "background": "#FF3333"
      }
      },

      "statusbar": {
      "style": "dark"
      }
    • 2.页面修改

      webview = plus.webview.create('test.html', 'test', {
      statusbar: {
      background: '#1478ee'
      }
      });

      webview = plus.webview.create('test.html', 'test', {
      titleNView: {
      titleText: '测试页',
      backgroundColor: '#fb6f18'
      }
      });
  • 6.app内容分享功能实现

      mounted(){
            if (window.plus) {
              this.plusReady();
              this.plusBtn = true
            } else {
              this.plusBtn = false
            }
          },
      methods: {
            plusReady() {
              this.updateSerivces();
            },
            /*获取分享服务列表*/
            updateSerivces() {
              var that = this
              plus.share.getServices(function (s) {
                for (var i in s) {
                  var t = s[i];
                  that.shares[t.id] = t;
                }
              }, function (e) {
                //outSet('获取分享服务列表失败:' + e.message);
              });
            },
            shareAction(sb, bh) {
              var that = this
              //outSet('分享操作:');
              if (!sb || !sb.s) {
                //outLine('无效的分享服务!');
                return;
              }
              var msg = {content: '这是一个分享测试', extra: {scene: sb.x}};
              if (bh) {
                msg.href = that.urls;  //分享链接
                msg.title = '瑞银通';  //分享标题
                msg.content = '下载并安装手机版';
                msg.thumbs = ['_www/logo.png'];
                msg.pictures = ['_www/logo.png'];
              }
              // 发送分享
              if (sb.s.authenticated) {
                //outLine('---已授权---');
                that.shareMessage(msg, sb.s);
              } else {
                //outLine('---未授权---');
                sb.s.authorize(function () {
                  that.shareMessage(msg, sb.s);
                }, function (e) {
                  //outLine('认证授权失败:' + e.code + ' - ' + e.message);
                });
              }
            },
            shareMessage(msg, s) {
              //outLine(JSON.stringify(msg));
              s.send(msg, function () {
                outLine('分享到"' + s.description + '"成功!');
              }, function (e) {
                //outLine('分享到"' + s.description + '"失败: ' + JSON.stringify(e));
              });
            },
    
            shareHref(inde) {
              var that = this
              var shareBts = [];
              // 更新分享列表
              var ss = that.shares['weixin'];
              if (navigator.userAgent.indexOf('qihoo') < 0) {  //在360流应用中微信不支持分享图片
                ss && ss.nativeClient && (shareBts.push({
                  title: '微信好友',
                  s: ss,
                  x: 'WXSceneSession'
                }), shareBts.push({title: '微信朋友圈', s: ss, x: 'WXSceneTimeline'}));
              }
              ss = that.shares['qq'];
              ss && ss.nativeClient && shareBts.push({title: 'QQ', s: ss});
              ss = that.shares['sinaweibo'];
              ss && shareBts.push({title: '新浪微博', s: ss});
              if (shareBts.length > 0) {
                if ((inde == 1 || inde == 2) && shareBts[inde - 1].s.id == 'weixin') {
                  that.shareAction(shareBts[inde - 1], true)
                } else if (inde == 3 && shareBts[inde - 1].s.id == 'qq') {
                  that.shareAction(shareBts[inde - 1], true)
                } else if (inde == 4 && shareBts[inde - 1].s.id == 'sinaweibo') {
                  that.shareAction(shareBts[inde - 1], true)
                } else {
                  that.$Toast('分享失败')
                }
              } else {
                plus.nativeUI.alert('当前环境无法支持分享链接操作!');
              }
            },
            shareBtn(x){
              var that = this
              that.$store.state.tit = that.name
              if (window.plus) {
                that.shareHref(x)
              } else {
                that.$Toast('该设备不支持分享功能')
              }
            }
          }
    
  • 7.app支付
    created(){
    this.plusReady()
    },
    methods: {
    /发送支付信息到后台/
    postOrders(){
    var that = this
    var url = that.inter.apidomain + '/Recharge/openVip' var data = { info: JSON.parse(JSON.parse(that.resultObj.rawdata).result).alipay_trade_app_pay_response, } that.axios.post(url, data).then(function (response) {
    if (response.data.error != 0) {
    that.Toast(response.data.message) setTimeout(function () { that.router.push({path: '/index'})
    }, 2000)
    } else if (response.data.error == 0) {
    setTimeout(function () {
    that.router.push({path: '/index'}) }, 2000) } }) }, /*支付按钮*/ /* submitBtn(){ var that = this var url = that.inter.apidomain + ' /Recharge/goToPay'
    var data = {id: that.idss}
    that.axios.post(url, data).then(function (response) { if (response.data.error != 0) { that.Toast(response.data.message)
    } else if (response.data.error == 0) {
    }
    })
    },*/
    plusReady() {
    var that = this
    // 获取支付通道
    plus.payment.getChannels(function (channels) {
    var txt = '支付通道信息:';
    for (var i in channels) {
    var channel = channels[i];
    if (channel.id == 'alipay') {
    if (channel.id == 'qhpay' || channel.id == 'qihoo') { // 过滤掉不支持的支付通道:暂不支持360相关支付
    continue;
    }
    that.pays[channel.id] = channel;
    txt += 'id:' + channel.id + ', ';
    txt += 'description:' + channel.description + ', ';
    txt += 'serviceReady:' + channel.serviceReady + '; ';
    that.zfbid = channel.id
    that.checkServices(channel);
    }
    }
    }, function (e) {
    });
    },

            // 检测是否安装支付服务
            checkServices(pc) {
              if (!pc.serviceReady) {
                var txt = null;
                switch (pc.id) {
                  case 'alipay':
                    txt = '检测到系统未安装“支付宝快捷支付服务”,无法完成支付操作,是否立即安装?';
                    break;
                  default:
                    txt = '系统未安装“' + pc.description + '”服务,无法完成支付,是否立即安装?';
                    break;
                }
                plus.nativeUI.confirm(txt, function (e) {
                  if (e.index == 0) {
                    pc.installService();
                  }
                }, pc.description);
              }
            },
            /*支付*/
            pay(id) {
              var that = this
              //检查是否请求订单中
              if (that.w) {
                return;
              }
              //outSet('----- 请求支付 -----');
              var url = that.PAYSERVER;
              if (id == 'alipay') {
                url += id;
              } else {
                plus.nativeUI.alert('当前环境不支持此支付通道!', null, '支付');
                return;
              }
              var appid = plus.runtime.appid;
              if (navigator.userAgent.indexOf('StreamApp') >= 0) {
                appid = 'Stream';
              }
              url += '&appid=' + appid + '&total=';
    
              that.w = plus.nativeUI.showWaiting();
              plus.payment.request(that.pays[id], that.orderInfo, function (result) {
                //that.resultObj = JSON.parse(result)
                that.resultObj = result
                plus.nativeUI.alert('支付成功', function () {
                  that.w.close();
                  that.postOrders()
                }, '支付');
              }, function (e) {
                plus.nativeUI.alert('错误', null, '支付失败:' + e.code);
                that.w.close();
                that.$router.push({path: '/index'})
              });
              // 请求支付订单
              /*var xhr = new XMLHttpRequest();
               xhr.onreadystatechange = function () {
               switch (xhr.readyState) {
               case 4:
               that.w.close();
               that.w = null;
               if (xhr.status == 200) {
               //                var order = xhr.responseText;
               plus.payment.request(that.pays[id], that.orderInfo, function (result) {
               plus.nativeUI.alert('支付成功', function () {
               back();
               }, '支付');
               }, function (e) {
               });
               } else {
               plus.nativeUI.alert('获取订单信息失败!', null, '支付');
               }
               break;
               default:
               break;
               }
               }
               xhr.open('GET', url + 0.01);
               console.log(url + 0.01)
               xhr.send();*/
            }
          }
    
  • 8.对element插件的日期格式进行转码
    getSTime1(val) {
    var date = new Date(Date.parse(val));
    this.value1 = date.getFullYear() + "-" + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + "-" + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
    },

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,855评论 1 4
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,517评论 0 38
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,011评论 0 2
  • ####工作内容1. 自学__markdown__语法。2. 参加培训课程,听老师__讲解考试题目__。3. 组织...
    djsecret阅读 241评论 0 1
  • 下了快一个月的雨,整个小城都浸泡在水中,湿得要发霉了,难得今天太阳露了个脸,久违的阳光一扫多日的阴郁。 家乡生活节...
    熙惜阅读 310评论 0 0