日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

Vue Bootstrap 结合学习笔记(一)

發(fā)布時(shí)間:2024/1/8 vue 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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ū)
    提供可用于拖拽到編輯區(qū)的所有組件,分類別展示

    該功能與本學(xué)習(xí)目的關(guān)聯(lián)不強(qiáng),且其主要拖拽功能比較花時(shí)間,暫且擱置
  • 頁面編輯區(qū)
    提供所有已添加到頁面的組件的編輯預(yù)覽,并提供組件增,刪,排版,選中功能

    增,刪,排版功能可以與模板區(qū)的拖拽功能結(jié)合,同樣暫時(shí)擱置
  • 組件配置區(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)前選中的組件上
    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;}}) }
    • 封裝編輯器的輸入框?yàn)榻M件如下:
    Vue.component('editor-text', {template: `<input v-model="vvalue" @change="$root.$emit('changeppt', name, vvalue)">`,props: ['name', 'value'],data() {return {vvalue: this.value}} })
    • 更改編輯器配置如下
    {.../*editor: `<input name="vtheme" :value="vtheme" /><input name="vpill" :value="vpill" /><input name="vtext" :value="vtext" />`,*/editor: `<editor-text name="vtheme" :value="theme" ></editor-text><input name="vpill" :value="pill" ></editor-text><input name="vtext" :value="text" ></editor-text>`,... }

    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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。