Vue Bootstrap 结合学习笔记(一)
生活随笔
收集整理的這篇文章主要介紹了
Vue Bootstrap 结合学习笔记(一)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文是不才在學(xué)習(xí)Vue和Bootstrap過程中遇到問題解決的一些思路,主要描述了項(xiàng)目搭建,組件封裝、獲取、編輯、更新的一步步實(shí)現(xiàn),一些解決方案也沒找到正確的官方API,還請大拿們多多提點(diǎn)。
項(xiàng)目介紹
旨在通過項(xiàng)目的形式同時(shí)學(xué)習(xí)Vue和Bootstrap,實(shí)現(xiàn)一個(gè)在線配置頁面的功能。通過Bootstrap封裝好的組件樣式提供界面需要的組件,通過Vue實(shí)現(xiàn)組件狀態(tài)更改及頁面渲染。
項(xiàng)目地址
https://github.com/shixia226/bootstrap-vue-designer
項(xiàng)目設(shè)計(jì)
-
組件模塊區(qū)
該功能與本學(xué)習(xí)目的關(guān)聯(lián)不強(qiáng),且其主要拖拽功能比較花時(shí)間,暫且擱置
提供可用于拖拽到編輯區(qū)的所有組件,分類別展示 -
頁面編輯區(qū)
增,刪,排版功能可以與模板區(qū)的拖拽功能結(jié)合,同樣暫時(shí)擱置
提供所有已添加到頁面的組件的編輯預(yù)覽,并提供組件增,刪,排版,選中功能 - 組件配置區(qū)
提供具體組件內(nèi)部狀態(tài)查看及更改功能
項(xiàng)目搭建
基本的項(xiàng)目搭建,創(chuàng)建index.html, index.js配置好webpack
<!doctype html> <html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><title>Vue Demo</title> </head> <body><script src="../index.js"></script> </body> </html> module.exports = {entry: './index.js',output: {filename: 'index.js'},module: {rules: [{test: /^[^.]+\.scss$/,use: ['style-loader','css-loader','sass-loader']}, {test: /(\.js|\.vue)$/,exclude: /(node_modules|bower_components)(?!.*webpack-dev-server)/,loader: 'babel-loader',query: {"presets": ["env"]}}]} };Bootstrap樣式引入
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">Vue框架引入
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>運(yùn)行
//node webpack-dev-server --port=9926 //Browser http://localhost:9926/第一個(gè)組件Badage
Bootstrap官網(wǎng)例子:
<span class="badge badge-light badge-pill">9</span>組件分析
- badge-light 樣式可以替換成badge-primary等,可以設(shè)置成屬性變量用于選擇哪個(gè)顏色;
- badge-pill 樣式有和無表現(xiàn)是不一樣的,可以設(shè)置屬性變量用于控制要不該樣式;
- 9 文本內(nèi)容作為最終的展示內(nèi)容,可以設(shè)置成屬性變量;
- 組件名取 widget-badge.
Vue組件封裝
Vue.component('widget-badge', {template: `<span :class="['badge', theme ? 'badge-' + theme : '', pill ? 'badge-pill' : '']">{{text}}</span>`,props: ['theme', 'pill', 'text'] });組件展示
html
<div class="app"><widget-badge></widget-badge> </div>js
new Vue({el: '.app' })組件配置
以上步驟后刷新瀏覽器應(yīng)該是可以看到組件效果了,但該組件的所有屬性都是在標(biāo)簽內(nèi)寫死的,無法在編輯頁面動(dòng)態(tài)設(shè)置
動(dòng)態(tài)屬性
- vue 中 props 屬性是不允許動(dòng)態(tài)更改的,一般都只能更改 data 中的屬性值,所以需要把 props 中的所有可變屬性拷貝一份到 data 中,且命名上不能相同,所以在此先規(guī)定 data 中的所有屬性都以字母'v'開頭;
-
每個(gè)可變屬性加一個(gè)編輯項(xiàng),對應(yīng)屬性名name="vpropA", 取值為當(dāng)前屬性值:value="vpropsA",所有的編輯項(xiàng)全部定義屬性 editor 上。
沒找到對應(yīng)獲取editor屬性值的API,但通過分析vue對象發(fā)現(xiàn)可以通過vue實(shí)例vm.$options.editor獲取到該定義值,暫且先就這么用著。
組件封裝更改如下:
Vue.component('widget-badge', {template: `<span :class="['badge', 'badge-' + vtheme, vpill ? 'badge-pill' : '']">{{vtext}}</span>`,props: ['theme', 'pill', 'text'],editor: `<input name="vtheme" :value="vtheme" /><input name="vpill" :value="vpill" /><input name="vtext" :value="vtext" />`,data() {return {vtheme: this.theme || 'secondary',vpill: this.pill,vtext: this.text || 'Badge'}} });屬性配置面板
- 點(diǎn)擊不同的組件要展示對應(yīng)的(不同的)配置面板
根據(jù)點(diǎn)擊元素獲取所屬vue組件
vue本來就是通過狀態(tài)更新的方式更改dom的,所以很少有dom相關(guān)的api,又只得分析vue實(shí)例里的數(shù)據(jù),發(fā)現(xiàn)$children好像就是直接下級組件的一個(gè)集合,且$children每一項(xiàng)里都又一個(gè)$el的屬性對應(yīng)到實(shí)際DOM元素 function getVueCmp(vm, elem) {let pelems = [],$root = vm.$el;while (elem !== $root) {pelems.push(elem);elem = elem.parentNode;}return getVueCmpByPelem(vm, pelems); } function getVueCmpByPelem(vm, pelems) {let $children = vm.$children;if ($children) {for (let i = 0, len = $children.length; i < len; i++) {let vcmp = $children[i],$el = vcmp.$el,idx = pelems.indexOf($el);if (idx !== -1) {pelems.length = idx;return getVueCmpByPelem(vcmp, pelems);}}}return vm; }增加點(diǎn)擊事件
<div class="app" @click="showPpt"><widget-badge></widget-badge> </div>獲取組件實(shí)時(shí)數(shù)據(jù)
根據(jù)前面的數(shù)據(jù)命名規(guī)則直接遍歷$data中所有以字母'v'開頭的屬性 function getVueCmpData(vcmp) {if (!vcmp) return {};let $data = vcmp.$data,data = {};let names = Object.getOwnPropertyNames($data);for (let i = 0, len = names.length; i < len; i++) {let name = names[i];if (name.charAt(0) === 'v') {data[name.substr(1)] = $data[name];}}return data; }數(shù)據(jù)更新
在vue根節(jié)點(diǎn)上設(shè)置全局監(jiān)聽事件,然后在屬性值中定義$emit方法觸發(fā)該監(jiān)聽事件- 根節(jié)點(diǎn)設(shè)置監(jiān)聽事件,并將監(jiān)聽結(jié)果反饋到當(dāng)前選中的組件上
- 封裝編輯器的輸入框?yàn)榻M件如下:
- 更改編輯器配置如下
vue最終初始化更改如下
new Vue({el: '.app',data: {pptCmp: undefined},watch: {pptCmp(vcmp) {new Vue({el: '.ppt',template: '<div class="ppt">' + (vcmp ? vcmp.$options.editor || '' : '') + '</div>',data() {return getVueCmpData(vcmp, true);},created() {this.$on('changeppt', function(name, value) {if (vcmp) {let names = name.split('.'),data = vcmp,len = names.length - 1;for (let i = 0; i < len; i++) {data = data[names[i]];}data[names[len]] = value;}})}})}},methods: {showPpt: function(evt) {let elem = evt.target;if (!document.querySelector('.ppt').contains(elem)) {let vcmp = getVueCmp(this, elem);if (vcmp === this.$root) {vcmp = null;}this.pptCmp = vcmp;}}} }總結(jié)
以上是生活随笔為你收集整理的Vue Bootstrap 结合学习笔记(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: macbook proa1708_苹果a
- 下一篇: vue笔记——本地应用