vue響應式原理,vuecli封裝組件并上傳至npm過程
效果圖和組件結構圖
el-table組件二次封裝過程
table主文(wen)件:index.vue
<template> <div> <el-table :data="tableData" style="width: 100%" @selection-change="handleSelectionChange" @sort-change="sortChageCallBack"> <el-table-column v-if="checkbox" type="selection" width="55"> </el-table-column> <el-table-column v-if="index" type="index" width="50"> </el-table-column> <template v-for="item in column"> <el-table-column :sort-by="item.sort_by" :sortable="item.sort" :align="item.align" :prop="item.prop" :label="item.label" :width="item.width"> <template slot-scope="scope"> <!-- 利用 type 屬性 判斷該列的類型 --> <!-- 插槽主要是實現操作列存放按鈕 --> <slot v-if="item.type === 'slot'" :name="item.slot_name" :data="scope.row" /> <!-- 通過動態組件渲染對應類型列 如文件列表處:function images switch text ,text為默認項 --> <component v-else :data="scope.row" :prop="item.prop" :config="item" :is="!item.type ? 'com-text' : `com-${item.type}`"> </component> </template> </el-table-column> </template> </el-table> </div></template><script>//自動化工程規則const modules = {}//讀取 control 文件夾const files = require.context("./control", true, /\index.vue$/) files.keys().forEach((item) => { const key = item.split("/") const component = files(item).default const name = key[1] //文件鏈接,后將文件通過擴展運算符 注冊組件 ...modules modules[`com-${name}`] = component //組裝組件 })export default { name: 'atable', inject: ['tableDataCllback', 'column'], props: { checkbox: Boolean, index: Boolean, checkList: { type: Array, default: () => [] }, getCallbackTitle:{ type: Function, default:()=>({}) } }, data() { return { str: '1' } }, components: { ...modules }, watch: { check_list(newval) { console.log(newval) } }, computed: { tableData() { return this.tableDataCllback() } }, methods: { handleSelectionChange(value) { console.log(value) this.$emit("update:checkList", value) }, sortChageCallBack(column, prop, order) { this.$emit("updataList") }, sendEmit(){ console.log("發送事件sendCallback") this.$emit("sendCallback") } }, mounted(){ console.log("這里是this.$parent") console.log(this.$parent) } }</script> <style scoped lang="scss"></style>
各個類型組件:
/src/components/table/control/text/index.vue
<!-- * @Descripttion: * @version: v.1 * @Author: 吳澤豪 * @Date: 2023-02-01 17:26:47 * @LastEditors: 吳澤豪 * @LastEditTime: 2023-02-01 21:57:20 --><template> <div> {{ data[prop] }} </div></template><script>export default { name: 'comText', props:{ data:{ type: Object, default: ()=>({}) }, prop:{ type: String, default: '' }, config:{ type: Object, default:()=>({}) } }, data() { return { } } }</script> <style scoped lang="scss"></style>
入口引用文件:
/src/views/content/index.vue
<!-- * @Descripttion: * @version: v.1 * @Author: 吳澤豪 * @Date: 2023-02-01 17:26:47 * @LastEditors: 吳澤豪 * @LastEditTime: 2023-02-04 13:43:30 --><template> <div> <div style="text-align: left;"> <el-button type="primary" @click="sendCallback" v-permiss="'list:send'">提交</el-button> <el-button type="danger" @click="deleteCallback" v-permiss="'list:deleteAll'">全部刪除</el-button> </div> <!-- 主要 --> <atable checkbox index :check-list.sync="check_list" @updataList="updataList" v-bind="$attrs" v-on="$listeners"> <template v-slot:opertions="slot"> <el-button @click="jum(slot.data.id)" type="primary">編輯</el-button> <el-button @click="deleteId(slot.data.id)" type="danger">刪除</el-button> </template> </atable> <!-- 主要 --> </div></template><script>export default { name: 'contents', data() { return { check_list: [], tableDatas: [] } }, provide() { return { tableDataCllback: () => this.tableDatas, column: [ { type: "function", label: "項目名稱", props: "data", align: "center", callback: (data) => { // function 類型會 并存在鏈接,可以在control處實現樣式 console.log(data) return `<a href="//www.baidu.com">${data.name}</a>` }, "width": "200px" }, { label: "項目狀態", prop: "status", align: "center", "width": "200px", type: 'switch' }, { label: "日期", prop: "datatime", align: "center", "width": "200px" }, { label: "名稱", prop: "name", align: "center", "width": "200px", sort: 'custom', sort_by: 'name-by' }, { label: "地址", prop: "address", align: "center", "width": "200px", sort: true }, { // type 為 slot 可以實現插槽 type: "slot", label: "操作", prop: "operation", slot_name: "opertions", align: "center", "width": "400px" } ] } }, components: { // 未從npm下載時用 // "a-table": () => import('@/components/table') }, watch: { check_list: { handler(value) { // 監聽復選框的事件 console.log(value) } } }, methods: { // 按鈕的方法 jum(id) { alert("編輯id為:" + id + "數據") }, deleteId(id) { alert("刪除id為:" + id + "數據") }, sendCallback() { if (this.check_list.length < 1) { alert("請選擇數據"); return; } alert("提交:" + this.check_list) }, deleteCallback() { if (this.check_list.length < 1) { alert("請選擇數據"); return; } alert("刪除:" + this.check_list) }, updataList() { // 排序請求數據,通過后端查詢條件請求渲染 setTimeout(() => { this.tableDatas = [{ datatime: '2016-05-01', name: '李明', address: '廣州 1519 號' }, { datatime: '2016-05-02', name: '劉洲', address: '廣州 1518 號', id: 0 }, { datatime: '2016-05-04', name: '王青', address: '廣州 1517 號' }, { datatime: '2016-05-03', name: '小豪', address: '廣州 1516 號' }]; }, 200); } }, mounted() { // 請求數據, console.log("這里是this.$children:") console.log(this.$children) setTimeout(() => { this.tableDatas = [{ datatime: '2016-05-02', name: '劉洲', address: '廣州 1518 號', id: 0 }, { datatime: '2016-05-04', name: '王青', address: '廣州 1517 號' }, { datatime: '2016-05-01', name: '李明', address: '廣州 1519 號' }, { datatime: '2016-05-03', name: '小豪', address: '廣州 1516 號' }]; }, 200); } }</script> <style scoped lang="scss"></style>
將組件包上傳至npm
1、注冊賬號: 鏈接: //www.npmjs.com/ (賬號、郵箱(密(mi)碼(ma)找回)、密(mi)碼(ma))
2、包準備
在項目(mu)里創建(jian)一(yi)個(ge)(ge)文件(jian)(jian)夾存放(fang)所有的(de)封(feng)(feng)裝組(zu)件(jian)(jian),并(bing)將封(feng)(feng)裝的(de)組(zu)件(jian)(jian)整個(ge)(ge)文件(jian)(jian)夾(table)放(fang)置在package文件(jian)(jian)夾內并(bing)創建(jian)一(yi)個(ge)(ge)組(zu)件(jian)(jian)注冊(ce)入口文件(jian)(jian)index.js,如:
package組(zu)件注冊入口文件 /package/index.js
/* * @Descripttion: * @version: v.1 * @Author: 吳澤豪 * @Date: 2023-02-03 10:22:24 * @LastEditors: 吳澤豪 * @LastEditTime: 2023-02-04 13:13:01 *///所有組件注冊入口,批量注冊import aTable from "../package/table/index.vue"const coms = [aTable]const install = function(Vue){ coms.forEach(com=>{ Vue.component(com.name, com) }) } export default install
3、打包
在總項(xiang)目 /package.json創建打包命令package
"scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "package": "vue-cli-service build --target lib ./src/package/index.js --name t-table --dest a-table" }, —target lib 指定打包目錄 —name 打包后的文件名字 —dest 打包后的文件夾名稱
運行 npm run package 生成包,如(ru)圖(tu):
4、上(shang)傳準備(bei)條件,創建/a-table/package.json,對應(ying)寫名稱(唯一)
{ "name": "wzh-table", "version": "1.0.1", "description": "", "main": "t-table.common.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC"}
5、上(shang)傳(將 npm 包 切(qie)換(huan)到官網(wang)源,不要用淘寶(bao)源)
登(deng)錄時會提(ti)示打開瀏覽器登(deng)錄,登(deng)陸后就會把Access Tokens加入npm
6、之后(hou)執行 npm publish
7、下載使用命令
npm i wzh-table --legacy-peer-deps
8、引入使用
/* * @Descripttion: * @version: v.1 * @Author: 吳澤豪 * @Date: 2023-02-01 17:16:34 * @LastEditors: 吳澤豪 * @LastEditTime: 2023-02-04 12:54:37 */import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';import hasPermiss from '@/utlis/permission'// 引入import wzhtable from 'wzh-table'Vue.config.productionTip = falseVue.use(ElementUI)//注冊Vue.use(wzhtable)//自定義的指令插件Vue.use(hasPermiss)new Vue({ router, store, render: h => h(App) }).$mount('#app')