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>
- 1.子组件
- 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>
- 1.父组件
- 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!"
- 也可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。
-
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!'
}
})
- (1)示例
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.路由传参
-
{ path: '/user/:id', component: User }
this.$route.params.id`
-
-
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
- main.js
*import store from './vuex/index'
- main.js
-
- 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 }
-
-
getter (可以认为是 store 的计算属性,Getter 接受 state 作为其第一个参数)
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
this.$store.getters.doneTodos
-
-
Mutation (Vuex 中的 mutation 非常类似于事件,Mutation 接受 state 作为其第一个参数)
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
this.$store.commit('increment')
-
- Action (Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作)
-
和mutations主要区别就是异步
mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } <!-- 触发 --> this.$store.dispatch('increment')
-
- Action (Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作)
-
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>
})
- npm install vue vue-server-renderer --save
十五.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'
}
});
- 1.在manifest.json->plus节点下加:
-
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());
},