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());
},