Vite 分頁邏輯與搜尋功能(語法糖)

// 註解A:在迭代物件屬性時,使用 for…in 迭代物件屬性 參考

  • A搜尋功能: 綁定搜尋表單,使用computed(計算功能)如果搜尋表單沒有值=>返回獲取到的陣列;如果有那就搜尋表單去除空白與大小寫 indexOf !==-1,返回它 並返回陣列
    filter() js 過濾功能 filter() js
    indexOf 找出元素索引值的陣列 indexOf js
  • B分頁總數:過濾的總筆數除以每頁筆數,「無條件進位」=>Math.ceil():公式:Math.ceil(過濾的總筆÷每頁筆數)
    Math.ceil 無條件進位 javaScript 浮點數計算
  • C分頁項目
    1.計算出每一頁的第一個索引數(使用computed(計算功能))=>當前頁面乘以每一頁減去每一頁=>最少都會在第一頁
    2.返回 => 搜尋後(過濾後)=>arr.slice([begin[, end]])回傳一個新陣列物件
    slice() js 給予開始或是結束索引,回傳一個新陣列物件 參閱slice() js
  • 選擇每頁顯示幾筆數據 v-model="pageValue" 綁定表單 ,函式 => @change="changeItemsPerPage($event)"

以下是程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<template>
<div class="checkWork_area">
<div class="search_bar_group">
<button class="el-button el-button--primary"> 導出Excel</button>
<!--綁定input v-model="searchQuery"-->
<input class="el-input__inner"
v-model="searchQuery" placeholder="search"/>
<i class="icon-search"></i>
</div>
<!----table-->
<div class="check_table_area">
<tr>
<th v-for="(item,thid) in tableHeader" :key="thid">
{{item.subject}}
</th>
</tr>
<tbody>
<!--過濾以後才開始分頁排列-->
<tr v-for="(item,index) in paginatedItems" :key="index">
<td>{{ Number(index+1 + startIndexValue) }}</td>
<td>{{ item.title }}</td>
<td>{{item.sourceWebName}}</td>
<td>{{ item.startDate}}</td>
</tr>
</tbody>
</div>

<!--*分頁-->
<ul class="pagination">
<!--如果在第一頁時 上一頁就是disabled-->
<li :class="{ 'disabled': currentPage === 1 }" >
<a @click="prevPage">
<i class="icon-chevron-left-solid"></i>
</a>
</li>
<!--總頁數遍歷 =>如果當頁的點擊的 page就是active -->
<li v-for="(n,index ) in totalPages" :key="index" @click="itActive(n)"
:class="{ 'active': n === currentPage }" >
<a>{{ n }}</a>
</li>
<!--如果在當前頁面等於總頁數就是disabled-->
<li
:class="{ 'disabled': currentPage === totalPages }" >
<a @click="nextPage">
<i class="icon-chevron-right-solid"></i></a>
</li>
<li>共{{ paginatedItems.length }}筆</li>
<li>
<el-select
v-model="pageValue"
class="m-2"
placeholder="Select"
style="width: 240px"
@change="changeItemsPerPage($event)"
>
<el-option
v-for="item in pagePerOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</li>
</ul>
</div>
</template>

<script setup lang="ts">
import axios from 'axios';
import { ref, onMounted, computed } from 'vue';
// 搜尋表單綁定
const searchQuery = ref<string>('');
// 當前頁面
const currentPage = ref<number>(1);
// 每頁幾筆
const itemsPerPage = ref<number>(10);
//選擇每頁顯示幾筆
const changeItemsPerPage = (event: number) => {
itemsPerPage.value = event;
}
const pagePerOptions = [
{ value: '10', label: '10筆' },
{ value: '15', label: '15筆' },
{ value: '20', label: '20筆' },
{ value: '30', label: '30筆' },
{ value: '40', label: '40筆' },
{ value: '50', label: '50筆' },
]
const pageValue = ref<string>('10筆');
interface tableHeaderType {
subject?: string;
thid?: string;
}
const tableHeader = ref<tableHeaderType[]>([
{ subject: '項目', thid: 'item' },
{ subject: '主題', thid: 'title' },
{ subject: '來源', thid: 'orange' },
{ subject: '開始時間', thid: 'startTime' }
])
// listType屬性
interface listsType {
UID?: string;
version?: string;
category?: string;
comment?: string;
descriptionFilterHtml?: string;
discountInfo?: string;
editModifyDate?: string;
hitRate?: number;
imageUrl?: string;
masterUnit?: object;
title?: string | any;
sourceWebName?: string | any;
startDate?: string | any;
}
// 表格數據
const lists = ref<listsType[]>([]);
// A搜尋功能過濾:綁定搜尋表單,使用computed(計算功能)如果搜尋表單沒有值=>返回獲取到的陣列;如果有那就搜尋表單去除空白與大小寫 indexOf !==-1,返回它 並返回陣列
const filteredItems = computed(() => {
let filteredItems = lists.value;
if (searchQuery.value === '') {
return filteredItems;
}
searchQuery.value = searchQuery.value.trim().toLowerCase();
filteredItems = filteredItems.filter(function (opt: listsType) {
// indexOf !==-1 =>
if (opt.title.toLowerCase().indexOf(searchQuery.value) !== -1 || opt.sourceWebName.toLowerCase().indexOf(searchQuery.value) !== -1) {
return opt;
}
})
return filteredItems;
})
// 索引數字
const startIndexValue = ref<number>(1);

// 總頁數
const totalPages = computed(() => {
// B分頁總數=>過濾的總筆數除以每頁筆數,「無條件進位」=>Math.ceil():公式:Math.ceil(過濾的總筆÷每頁筆數)
return Math.ceil(filteredItems.value.length / itemsPerPage.value);
})
// 分頁項目
const paginatedItems = computed(() => {
// 當前頁面乘以每一頁減去每一頁
const startIndex = currentPage.value * itemsPerPage.value - itemsPerPage.value;
startIndexValue.value = startIndex;
// 返回 => 搜尋後(過濾後)=>arr.slice([begin[, end]])回傳一個新陣列物件
return filteredItems.value.slice(startIndex, startIndex + itemsPerPage.value);
})
// 上一頁
const prevPage = () => {
// 如果當前頁面小於 < 1
if (currentPage.value > 1) {
currentPage.value--;
}
}
// 下一頁
const nextPage = () => {
// 如果當前頁面小於 < 全部頁面 =。那當前頁就能++
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
}
// 點擊獲得第幾頁塞入當前頁面
const itActive = (page: number) => {
// 如果當前頁面是null那當前頁面是第一頁,否則是點擊頁面
page === null ? currentPage.value = 1 : currentPage.value = page;
}
// 獲取數據
const getItems = async () => {
try {
const api = 'https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=200';
const res = await axios.get(api);
lists.value = res.data;
}
catch (err) {
console.log('err', err);
}
}
onMounted(() => {
getItems();
console.log(typeof pagePerOptions)
})
</script>

github 分頁邏輯說明

父傳子到子分頁

組件
v-model 的參數語法不會直接修改 props 的值 , 修改=>使用父組件 pageValue 父傳給子,@update:pageValue=”pageValue = $event”, 當 Pagination 组件觸發 update:pageValue 事件時,子組件会觸發 update:pageValue 的自定義事件,並將新值作為参数傳遞給父組件

父組件
引入Pagination.vue 子組件

<Pagination
:currentPage=”currentPage”
:totalPages=”totalPages”
:totoItem=”filteredItems.length”
:pagePerOptions=”pagePerOptions”
:pageValue=”pageValue”
@update:pageValue=”pageValue = $event”
@sendprevPage=”prevPage”
@sendNextPage=”nextPage”
@sendItActive=”itActive”
@sendOnChange=”changeItemsPerPage”
/>
傳值與接收子組件的通訊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<template>
<div class="checkWork_area">
<div class="search_bar_group">
<button class="el-button el-button--primary"> 導出Excel</button>
<!--綁定input v-model="searchQuery"-->
<input class="el-input__inner"
v-model="searchQuery" placeholder="search"/>
<i class="icon-search"></i>
</div>
<!----table-->
<div class="check_table_area">
<tr>
<th v-for="(item,thid) in tableHeader" :key="thid">
{{item.subject}}
</th>
</tr>
<tbody>
<!--過濾以後才開始分頁排列-->
<tr v-for="(item,index) in paginatedItems" :key="index">
<td>{{ Number(index+1 + startIndexValue) }}</td>
<td>{{ item.title }}</td>
<td>{{item.sourceWebName}}</td>
<td>{{ item.startDate}}</td>

</tr>
</tbody>
</div>

<!--子組件Pagination -->
<Pagination
:currentPage="currentPage"
:totalPages="totalPages"
:totoItem="filteredItems.length"
:pagePerOptions="pagePerOptions"
:pageValue="pageValue"
@update:pageValue="pageValue = $event"
@sendprevPage="prevPage"
@sendNextPage="nextPage"
@sendItActive="itActive"
@sendOnChange="changeItemsPerPage"
/>
</div>
</template>

<script setup lang="ts">
import axios from 'axios';
import { ref, onMounted, computed } from 'vue';
import Pagination from '../components/Pagination.vue';
// 搜尋表單綁定
const searchQuery = ref<string>('');
// 當前頁面
const currentPage = ref<number>(1);
// 每頁幾筆
const itemsPerPage = ref<number>(10);
const changeItemsPerPage = (event: number) => {
itemsPerPage.value = event;
}
const pagePerOptions = [
{ value: '10', label: '10筆' },
{ value: '15', label: '15筆' },
{ value: '20', label: '20筆' },
{ value: '30', label: '30筆' },
{ value: '40', label: '40筆' },
{ value: '50', label: '50筆' },
]
const pageValue = ref<string>('10筆');
interface tableHeaderType {
subject?: string;
thid?: string;
}
const tableHeader = ref<tableHeaderType[]>([
{ subject: '項目', thid: 'item' },
{ subject: '主題', thid: 'title' },
{ subject: '來源', thid: 'orange' },
{ subject: '開始時間', thid: 'startTime' }
])
// listType屬性
interface listsType {
UID?: string;
version?: string;
category?: string;
comment?: string;
descriptionFilterHtml?: string;
discountInfo?: string;
editModifyDate?: string;
hitRate?: number;
imageUrl?: string;
masterUnit?: object;
title?: string | any;
sourceWebName?: string | any;
startDate?: string | any;
}
// 表格數據
const lists = ref<listsType[]>([]);
// A搜尋功能過濾:綁定搜尋表單,使用computed(計算功能)如果搜尋表單沒有值=>返回獲取到的陣列;如果有那就搜尋表單去除空白與大小寫 indexOf !==-1,返回它 並返回陣列
const filteredItems = computed(() => {
let filteredItems = lists.value;
if (searchQuery.value === '') {
return filteredItems;
}
searchQuery.value = searchQuery.value.trim().toLowerCase();
filteredItems = filteredItems.filter(function (opt: listsType) {
// indexOf !==-1 =>
if (opt.title.toLowerCase().indexOf(searchQuery.value) !== -1 || opt.sourceWebName.toLowerCase().indexOf(searchQuery.value) !== -1) {
return opt;
}
})
return filteredItems;
})
// 索引數字
const startIndexValue = ref<number>(1);

// 總頁數
const totalPages = computed(() => {
// B分頁總數=>過濾的總筆數除以每頁筆數,「無條件進位」=>Math.ceil():公式:Math.ceil(過濾的總筆÷每頁筆數)
return Math.ceil(filteredItems.value.length / itemsPerPage.value);
})
// 分頁項目
const paginatedItems = computed(() => {
// 當前頁面乘以每一頁減去每一頁
const startIndex = currentPage.value * itemsPerPage.value - itemsPerPage.value;
startIndexValue.value = startIndex;
// 返回 => 搜尋後(過濾後)=>arr.slice([begin[, end]])回傳一個新陣列物件
return filteredItems.value.slice(startIndex, startIndex + itemsPerPage.value);
})
// 上一頁
const prevPage = () => {
// 如果當前頁面小於 < 1
if (currentPage.value > 1) {
currentPage.value--;
}
}
// 下一頁
const nextPage = () => {
// 如果當前頁面小於 < 全部頁面 =。那當前頁就能++
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
}
// 點擊獲得第幾頁塞入當前頁面
const itActive = (page: number) => {
// 如果當前頁面是null那當前頁面是第一頁,否則是點擊頁面
page === null ? currentPage.value = 1 : currentPage.value = page;
}
// 獲取數據
const getItems = async () => {
try {
const api = 'https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=200';
const res = await axios.get(api);
lists.value = res.data;
}
catch (err) {
console.log('err', err);
}
}
onMounted(() => {
getItems();
console.log(typeof pagePerOptions)
})
</script>

分頁的父傳子

新增Pagination.vue 子組件
使用=>import { defineProps } from ‘vue’;
// prop 接收物件設定type
const props = defineProps({
currentPage: { type: Number },
totalPages: { type: Number },
totoItem: { type: Number },
pagePerOptions: Object,
pageValue: { type: String },
})
// 父對子傳值
const emits = defineEmits([‘sendprevPage’, ‘sendNextPage’, ‘sendItActive’, ‘sendOnChange’]);
const sendprevPage = () => {
emits(‘sendprevPage’,)
}
const sendNextPage = () => {
emits(‘sendNextPage’,)
}
const sendItActive = (page: number) => {
emits(‘sendItActive’, page)
}
const sendOnChange = (event: number) => {
emits(‘sendOnChange’, event)
}

子組件=>Pagination.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<template>
<ul class="pagination">
<li :disabled="currentPage === 1">
<a @click="sendprevPage"><i class="icon-chevron-left-solid"></i></a>
</li>
<li v-for="(n, index ) in totalPages" :key="index" @click="sendItActive(n)"
:class="{ 'active': n === currentPage }">
<a> {{ n }}</a>
</li>
<li :disabled="currentPage === totalPages">
<a @click="sendNextPage">
<i class="icon-chevron-right-solid"></i>
</a>
</li>
<li>共{{ totoItem }}筆</li>
<li>
<el-select
:model-value="pageValue"
@update:model-value="$emit('update:pageValue', $event)"
class="m-2"
placeholder="Select"
style="width: 240px"
@change="sendOnChange($event)">
<el-option v-for="item in pagePerOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</li>
</ul>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { defineProps } from 'vue'
const props = defineProps({
currentPage: { type: Number },
totalPages: { type: Number },
totoItem: { type: Number },
pagePerOptions: Object,
pageValue: { type: String },

})


const emits = defineEmits(['sendprevPage', 'sendNextPage', 'sendItActive', 'sendOnChange']);
const sendprevPage = () => {
emits('sendprevPage',)
}
const sendNextPage = () => {
emits('sendNextPage',)
}
const sendItActive = (page: number) => {
emits('sendItActive', page)
}
const sendOnChange = (event: number) => {
emits('sendOnChange', event)
}
</script>
github 分頁邏輯,分頁可選每頁頁數與搜尋功能,父子間的通訊 父子間的通訊

GitHub 說明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<style lang="scss" scoped>
.active {
a {
color: red;
border-bottom:2px solid #3333;
}
}
.pagination{
display: flex;
justify-content: center;
list-style-type:none;
> li {
margin: auto 10px;
list-style-type:none;
a{
background-color: #b0cbfb;
border: 2px solid #3f51b5;
border-radius: 9999rem;
color:#3f51b5;
display: block;
height: 30px;
line-height: 30px;
text-align: center;
width: 30px;
&:hover{
background-color: #3f51b5;
border: 2px solid #3f51b5;
color:#ffff;
}
}
&.disabled{
color:#ddd;
cursor: not-allowed;
a{
background-color: #dddddd;
border: 2px solid #b0cbfb;
border-radius: 9999rem;
color:#c9c2c2;
display: block;
height: 30px;
line-height: 30px;
text-align: center;
width: 30px;
}
}
}
}
</style>

VueCli Event Bus

創建bus.js文件

新增utils資料夾,新增 bus.js
bus.js內容如下
引入Vue導出EventBus

1
2
import Vue from "vue";
export const EventBus = new Vue();

1.傳送:在發送組件的組件調用$emit發送數據的方法

import { EventBus } from “../utils/bus.js”
EventBus.$emit(‘定義一個名字’, 參數2:’要發送的數據’)

2.接收:數據的組件中調用$on方法監聽mounted

import { EventBus } from “../utils/bus.js”

// 接收數據
EventBus.$on(‘定義一個名字’, 參數2:’(value)=>{
// value是接收的數據
this.message=value;
}’)

3.銷毀監聽

beforeDestroy() {
// 銷毁監聽
EventBus.$off(“clickSendMsg”);
EventBus.$off(“clickToMsg”);
},

VueCli 安裝 jquery

VueCli 安裝 jquery

執行指令

1
2
npm install jquery --save

在build/webpack.base.conf文件當中引入jquery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
...
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
// 引入jquery
'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery')
}
},
...
}

VueCli Prop

VueCli Prop 父傳子

新增Child.vue

父為Home.vue
1.引入Child.vue
註冊
2.components: {
Child
},
3.在template 下新增
4.子組件prop寫好後,到父組往下傳值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Home.vue
<template>
<div class="home">
<Child :interest="interest" :lists="lists"/>
</div>
</template>

<script>
import Child from './Child.vue'
export default {
name: 'Home',
components: {
Child
},
data () {
return {
msg: 'Welcome to Your Vue.js App',
interest:'游泳',
lists:[
{id:'001',todo:'去旅行'},
{id:'002',todo:'寫部落格'}
]
}
}
}
</script>

子組件 Child.vue

script新增
props : {
interest : {
type : String,
require : true
},
lists:{
type : Object,
require : true
}
}
template新增

1
2
3
4
5
6
<h2>興趣:{{ interest }}</h2>
<ul>
<li v-for="item in lists" :key="item">
{{item.todo}}
</li>
</ul>

子組件完整組件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//Child.vue
<template>
<div class="home">
<h2>興趣:{{ interest }}</h2>
<ul>
<li v-for="item in lists" :key="item">
{{item.todo}}
</li>
</ul>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
props : {
interest : {
type : String,
require : true
},
lists:{
type : Object,
require : true
}
}
}
</script>

GitHub VueCli prop 父傳子

參考資料
VueCli(Vue2) prop 父傳子

VueCli(Vue2) 單元測試

jest 官網
Jest 是一個由Facebook 開發的 test runner,它提供許多豐富的功能,例如:斷言、分析測試涵蓋率、 mock 功能與良好的錯誤提示訊息等。
Vue Test Utils

1
2
3
4
5
6
nvm use 14.17.0
//安裝vue/cli
npm install -g @vue/cli
//vue檢查版本號
vue --version
//@vue/cli 5.0.8

創建專案

1
2
3
4
5
6
7
8
9
10
11
12
13

vue create 專案名稱 -m npm

Vue CLI v5.0.8
? Please pick a preset:
te ([Vue 3] babel, router)
vue3 ([Vue 3] babel, eslint)
element-plus ([Vue 3] dart-sass, babel, router, vuex, unit-jest)
Default ([Vue 3] babel, eslint)
❯ Default ([Vue 2] babel, eslint)
Manually select features

Creating project in /Users/larahuang/vuecli_5.0.8_2.

如果您使用 Vue CLI 建立項目,則可以使用該插件運行 Jest 測試。
unit-jest

1
2
cd 專案名稱
vue add unit-jest
運行
1
npm run test:unit

VueCli axios安裝與使用

安裝vue-axios

axios 官網

1
npm install --save axios@0.26.1 vue-axios@3.4.1

在main.js
引入axios =>使用 VueAxios, axios

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'//引入axios
import VueAxios from 'vue-axios'//引入VueAxios

Vue.use(VueAxios, axios)
Vue.config.productionTip = false

axios.defaults.headers.post['Content-Type'] = ['application/json;charset=UTF-8']

/* eslint-disable no-new */
export const app = new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})

在App.vue測試

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>
import axios from 'axios'
export default {
name: 'App',
data () {
return {
info:[],
}
},
created() {
this.getWeatherApi();
this.getLists();
},

methods:{
getWeatherApi(){
const api =`${process.env.API_PATH}/data/2.5/forecast?q=Taipei,tw&APPID=${process.env.APP_ID}&lang=zh_tw&units=metric`;
axios
.get(api)
.then(res => (
this.info = res, console.log('info',this.info)
))
},
getLists (){
const api ='https://api.coindesk.com/v1/bpi/currentprice.json';
this.$http.get(api).then((res) => {
console.log(res.data);
});

}
},

}
</script>

axios 設置與使用

VueCli(Vue2) 環境變數

VueCli(Vue2) 環境變數

在config資料夾內dev.env.js,prod.env.js
加入APIPATH, APPID 雙影號

1
2
3
4
5
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
APIPATH: '"https://xxx.com.tw"',
APPID: '"1234567"',
})

測試是否抓取到值,到App.vue

process.env.API_PATH, process.env.APP_ID

1
2
3
4
5
6
export default {
name: 'App',
created(){
console.log(process.env.API_PATH, process.env.APP_ID);
}
}

環境變數的設置與使用