vue從入門到進階:組件Component詳解(六)

来源:https://www.cnblogs.com/moqiutao/archive/2018/01/22/8328931.html
-Advertisement-
Play Games

一.什麼是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。 所有的 Vue ...


一.什麼是組件?

組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現為用 is 特性進行了擴展的原生 HTML 元素。

所有的 Vue 組件同時也都是 Vue 的實例,所以可接受相同的選項對象 (除了一些根級特有的選項) 並提供相同的生命周期鉤子。

二.註冊組件

全局註冊

html代碼:

<div id="example">
  <my-component></my-component>
</div>

JS代碼:

// 註冊
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
var vm = new Vue({
  el: '#example',
  data: {
       
  } 
})

渲染結果為:

<div id="example">
  <div>A custom component!</div>
</div>

或者另外一種註冊方式,通過 全局API:Vue.extend()
代碼如下:

// 註冊
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
});

// 註冊
Vue.component('my-component', MyComponent);
var vm = new Vue({
  el: '#example',
  data: {
       
  }
})

Vue.extend()使用說明

下麵說明下Vue.extend( options )的使用。
參數:{Object} options
用法:使用基礎 Vue 構造器,創建一個“子類”。參數是一個包含組件選項的對象
data 選項是特例,需要註意 - 在 Vue.extend() 中它必須是函數

<div id="mount-point"></div>
// 創建構造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 創建 Profile 實例,並掛載到一個元素上。
new Profile().$mount('#mount-point')

結果如下:

<p>Walter White aka Heisenberg</p>

上面又用到了實例方法vm.$mount(),下麵說明下它的使用方式。

vm.$mount( [elementOrSelector] )使用說明

參數:

  • {Element | string} [elementOrSelector]
  • {boolean} [hydrating]

返回值:vm - 實例自身
用法:
如果 Vue 實例在實例化時沒有收到 el 選項,則它處於“未掛載”狀態,沒有關聯的 DOM 元素。可以使用 vm.$mount() 手動地掛載一個未掛載的實例。

如果沒有提供 elementOrSelector 參數,模板將被渲染為文檔之外的的元素,並且你必須使用原生 DOM API 把它插入文檔中。

這個方法返回實例自身,因而可以鏈式調用其它實例方法。

var MyComponent = Vue.extend({
  template: '<div>Hello!</div>'
})

// 創建並掛載到 #app (會替換 #app)
new MyComponent().$mount('#app')

// 同上
new MyComponent({ el: '#app' })

// 或者,在文檔之外渲染並且隨後掛載
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)

局部註冊

你不必把每個組件都註冊到全局。你可以通過某個 Vue 實例/組件的實例選項 components 註冊僅在其作用域中可用的組件:

var Child = {
  template: '<div>A custom component!</div>'
}

new Vue({
  // ...
  components: {
    // <my-component> 將只在父組件模板中可用
    'my-component': Child
  }
})

這種封裝也適用於其它可註冊的 Vue 功能,比如指令

DOM 模板解析註意事項

<ul>、<ol>、<table>、<select> 這樣的元素里允許包含的元素有限制,而另一些像 <option> 這樣的元素只能出現在某些特定元素的內部。

例如:

<table>
  <my-row>...</my-row>
</table>

自定義組件 <my-row> 會被當作無效的內容,因此會導致錯誤的渲染結果。變通的方案是使用特殊的 is 特性:

<table>
  <tr is="my-row"></tr>
</table>

應當註意,如果使用來自以下來源之一的字元串模板,則沒有這些限制:

  • <script type="text/x-template">
  • JavaScript 內聯模板字元串
  • .vue 組件

因此,請儘可能使用字元串模板。

data 必須是函數

如下代碼:

Vue.component('my-component', {
  template: '<span>{{ message }}</span>',
  data: {
    message: 'hello'
  }
})

那麼 Vue 會停止運行,併在控制台發出警告,告訴你在組件實例中 data 必須是一個函數。
我們來理解下,看下麵代碼:

<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>
var data = { counter: 0 }

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // 技術上 data 的確是一個函數了,因此 Vue 不會警告,
  // 但是我們卻給每個組件實例返回了同一個對象的引用
  data: function () {
    return data
  }
})

new Vue({
  el: '#example-2'
})

由於這三個組件實例共用了同一個 data 對象,因此遞增一個 counter 會影響所有組件!這就錯了。我們可以通過為每個組件返回全新的數據對象來修複這個問題:

data: function () {
  return {
    counter: 0
  }
}

現在每個 counter 都有它自己內部的狀態了,不會相互影響。

三.Prop

最常見的應用就是:組件 A 在它的模板中使用了組件 B。它們之間必然需要相互通信:父組件可能要給子組件下發數據,子組件則可能要將它內部發生的事情告知父組件。

在 Vue 中,父子組件的關係可以總結為 prop 向下傳遞,事件向上傳遞。父組件通過 prop 給子組件下發數據,子組件通過事件給父組件發送消息。

使用 Prop 傳遞數據

實例1:

Vue.component('child', {
  // 聲明 props
  props: ['message'],
  // 就像 data 一樣,prop 也可以在模板中使用
  // 同樣也可以在 vm 實例中通過 this.message 來使用
  template: '<span>{{ message }}</span>'
})

<child message="hello!"></child>

結果:hello!

實例2:
HTML 特性是不區分大小寫的。所以,當使用的不是字元串模板時,camelCase (駝峰式命名) 的 prop 需要轉換為相對應的 kebab-case (短橫線分隔式命名):

Vue.component('child', {
  // 在 JavaScript 中使用 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})

<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child>

如果你使用字元串模板,則沒有這些限制。

動態 Prop

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

你也可以使用 v-bind 的縮寫語法:

<child :my-message="parentMsg"></child>

(重要)如果你想把一個對象的所有屬性作為 prop 進行傳遞,可以使用不帶任何參數的 v-bind (即用 v-bind 而不是 v-bind:prop-name)。例如,已知一個 todo 對象:

todo: {
  text: 'Learn Vue',
  isComplete: false
}

然後:

<todo-item v-bind="todo"></todo-item>

將等價於:

<todo-item
  v-bind:text="todo.text"
  v-bind:is-complete="todo.isComplete"
></todo-item>

字面量語法 vs 動態語法

初學者常犯的一個錯誤是使用字面量語法傳遞數值:

<!-- 傳遞了一個字元串 "1" -->
<comp some-prop="1"></comp>

因為它是一個字面量 prop,它的值是字元串 "1" 而不是一個數值。如果想傳遞一個真正的 JavaScript 數值,則需要使用 v-bind,從而讓它的值被當作 JavaScript 表達式計算:

<!-- 傳遞真正的數值 -->
<comp v-bind:some-prop="1"></comp>

單向數據流

Prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是反過來不會。這是為了防止子組件無意間修改了父組件的狀態,來避免應用的數據流變得難以理解。

另外,每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味著你不應該在子組件內部改變 prop。如果你這麼做了,Vue 會在控制台給出警告。

在兩種情況下,我們很容易忍不住想去修改 prop 中數據:

  • Prop 作為初始值傳入後,子組件想把它當作局部數據來用;
  • Prop 作為原始數據傳入,由子組件處理成其它數據輸出。

對這兩種情況,正確的應對方式是:
1.定義一個局部變數,並用 prop 的值初始化它:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

2.定義一個計算屬性,處理 prop 的值並返回:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

註意在 JavaScript 中對象數組是引用類型,指向同一個記憶體空間,如果 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。

Prop 驗證

我們可以為組件的 prop 指定驗證規則。如果傳入的數據不符合要求,Vue 會發出警告。
要指定驗證規則,需要用對象的形式來定義 prop,而不能用字元串數組

Vue.component('example', {
  props: {
    // 基礎類型檢測 (`null` 指允許任何類型)
    propA: Number,
    // 可能是多種類型
    propB: [String, Number],
    // 必傳且是字元串
    propC: {
      type: String,
      required: true
    },
    // 數值且有預設值
    propD: {
      type: Number,
      default: 100
    },
    // 數組/對象的預設值應當由一個工廠函數返回
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定義驗證函數
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

type 可以是下麵原生構造器:String ,Number,Boolean,Function,Object,Array,Symbol。

type 也可以是一個自定義構造器函數,使用 instanceof 檢測。

prop 驗證失敗,Vue 會拋出警告 (如果使用的是開發版本)。註意 prop 會在組件實例創建之前進行校驗,所以在 defaultvalidator 函數里,諸如 datacomputedmethods 等實例屬性還無法使用。

其它實例:

Vue.component('modal', {
  template: '#modal-template',
  props: {
    show: {
      type: Boolean,
      required: true,
      twoWay: true    
    }
  }
});

twoWay Prop 的參數 移除。Props 現在只能單向傳遞。為了對父組件產生反向影響,子組件需要顯式地傳遞一個事件而不是依賴於隱式地雙向綁定。所以上面的的最後一個實例只是貼出來代碼而已,最新版本已經移除了。

四.非Prop特性

所謂非 prop 特性,就是指它可以直接傳入組件,而不需要定義相應的 prop。

儘管為組件定義明確的 prop 是推薦的傳參方式,組件的作者卻並不總能預見到組件被使用的場景。所以,組件可以接收任意傳入的特性,這些特性都會被添加到組件的根元素上

例如,假設我們使用了第三方組件 bs-date-input,它包含一個 Bootstrap 插件,該插件需要在 input 上添加 data-3d-date-picker 這個特性。這時可以把特性直接添加到組件上 (不需要事先定義 prop):

<bs-date-input data-3d-date-picker="true"></bs-date-input>

添加屬性 data-3d-date-picker="true" 之後,它會被自動添加到 bs-date-input 的根元素上。

假設這是 bs-date-input 的模板:

<input type="date" class="form-control">

為了給該日期選擇器插件增加一個特殊的主題,我們可能需要增加一個特殊的 class,比如:

<bs-date-input
  data-3d-date-picker="true"
  class="date-picker-theme-dark"
></bs-date-input>

最終在根元素上生成的class值為:form-control date-picker-theme-dark。

五.自定義事件

我們知道,父組件使用 prop 傳遞數據給子組件。但子組件怎麼跟父組件通信呢?這個時候 Vue 的自定義事件系統就派得上用場了。

使用 v-on 綁定自定義事件

每個 Vue 實例都實現了事件介面,即:

  • 使用 $on(eventName) 監聽事件
  • 使用 $emit(eventName) 觸發事件

Vue 的事件系統與瀏覽器的 EventTarget API 有所不同。儘管它們的運行起來類似,但是 $on $emit 並不是addEventListener dispatchEvent 的別名。

另外,父組件可以在使用子組件的地方直接用 v-on 來監聽子組件觸發的事件。

不能用 $on 偵聽子組件釋放的事件,而必須在模板里直接用 v-on 綁定,參見下麵的例子。

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
  template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

給組件綁定原生事件.native

有時候,你可能想在某個組件的根元素上監聽一個原生事件。可以使用 v-on 的修飾符 .native。例如:

<my-component v-on:click.native="doTheThing"></my-component>

.sync 修飾符(2.3.0+)

<comp :foo.sync="bar"></comp>

會被擴展為:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

當子組件需要更新 foo 的值時,它需要顯式地觸發一個更新事件:

this.$emit('update:foo', newValue)

使用自定義事件的表單輸入組件

自定義事件可以用來創建自定義的表單輸入組件,使用 v-model 來進行數據雙向綁定。要牢記:

<input v-model="something">

這不過是以下示例的語法糖:

<input
  v-bind:value="something"
  v-on:input="something = $event.target.value">

所以在組件中使用時,它相當於下麵的簡寫:

<custom-input
  v-bind:value="something"
  v-on:input="something = arguments[0]">
</custom-input>

所以要讓組件的 v-model 生效,它應該 (從 2.2.0 起是可配置的):

  • 接受一個 value prop
  • 在有新的值時觸發 input 事件並將新值作為參數

例子1:

<div id="app">
      <custom-input v-model="something"></custom-input>
    <br/>
    {{something}}
</div>
// 註冊
Vue.component('custom-input', {
  props:['something'],
  template: '<input type="text"  v-bind:value="something" v-on:input="updateValue($event.target.value)"/>',
  methods:{
      updateValue:function(value){
           this.$emit('input', value)
      }
  }
})
var vm = new Vue({
  el: '#app',
  data: {
       something:''
  }
  
})

例子2:貨幣輸入的自定義控制項

<currency-input v-model="price"></currency-input>
Vue.component('currency-input', {
  template: '\
    <span>\
      $\
      <input\
        ref="input"\
        v-bind:value="value"\
        v-on:input="updateValue($event.target.value)"\
      >\
    </span>\
  ',
  props: ['value'],
  methods: {
    // 不是直接更新值,而是使用此方法來對輸入值進行格式化和位數限制
    updateValue: function (value) {
      var formattedValue = value
        // 刪除兩側的空格符
        .trim()
        // 保留 2 位小數
        .slice(
          0,
          value.indexOf('.') === -1
            ? value.length
            : value.indexOf('.') + 3
        )
      // 如果值尚不合規,則手動覆蓋為合規的值
      if (formattedValue !== value) {
        this.$refs.input.value = formattedValue
      }
      // 通過 input 事件帶出數值
      this.$emit('input', Number(formattedValue))
    }
  }
})

實例3:更加完善的貨幣過濾器

<div id="app">
  <currency-input 
    label="Price" 
    v-model="price"
  ></currency-input>
  <currency-input 
    label="Shipping" 
    v-model="shipping"
  ></currency-input>
  <currency-input 
    label="Handling" 
    v-model="handling"
  ></currency-input>
  <currency-input 
    label="Discount" 
    v-model="discount"
  ></currency-input>
  
  <p>Total: ${{ total }}</p>
</div>
Vue.component('currency-input', {
  template: '\
    <div>\
      <label v-if="label">{{ label }}</label>\
      $\
      <input\
        ref="input"\
        v-bind:value="value"\
        v-on:input="updateValue($event.target.value)"\
        v-on:focus="selectAll"\
        v-on:blur="formatValue"\
      >\
    </div>\
  ',
  props: {
    value: {
      type: Number,
      default: 0
    },
    label: {
      type: String,
      default: ''
    }
  },
  mounted: function () {
    this.formatValue()
  },
  methods: {
    updateValue: function (value) {
      var result = currencyValidator.parse(value, this.value)
      if (result.warning) {
        this.$refs.input.value = result.value
      }
      this.$emit('input', result.value)
    },
    formatValue: function () {
      this.$refs.input.value = currencyValidator.format(this.value)
    },
    selectAll: function (event) {
      // Workaround for Safari bug
      // http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome
      setTimeout(function () {
          event.target.select()
      }, 0)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    price: 0,
    shipping: 0,
    handling: 0,
    discount: 0
  },
  computed: {
    total: function () {
      return ((
        this.price * 100 + 
        this.shipping * 100 + 
        this.handling * 100 - 
        this.discount * 100
      ) / 100).toFixed(2)
    }
  }
})

自定義組件的 v-model(2.2.0 新增)

預設情況下,一個組件的 v-model 會使用 value prop 和 input 事件。但是諸如單選框、覆選框之類的輸入類型可能把 value 用作了別的目的。model 選項可以避免這樣的衝突:

Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean,
    // 這樣就允許拿 `value` 這個 prop 做其它事了
    value: String
  },
  // ...
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>

上述代碼等價於:

<my-checkbox
  :checked="foo"
  @change="val => { foo = val }"
  value="some value">
</my-checkbox>

註意你仍然需要顯式聲明 checked 這個 prop

完整的代碼:
html:

<div id="app">
      <my-checkbox v-model="foo" value="some value"></my-checkbox>
    {{foo}}
</div>

JS代碼:

Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean,
    // 這樣就允許拿 `value` 這個 prop 做其它事了
    value: String
  },
  template:'<input type="checkbox" @change="changefun(ischecked)"/>',
  data:function(){
      return {
          ischecked:this.checked
      }
  },
  methods:{
      changefun(state){
          this.ischecked = !state;
          this.$emit('change', this.ischecked);
      }
  }
})
var vm = new Vue({
  el: '#app',
  data: {
       foo:false
  }
  
})

非父子組件的通信

有時候,非父子關係的兩個組件之間也需要通信。在簡單的場景下,可以使用一個空的 Vue 實例作為事件匯流排:

var bus = new Vue()
// 觸發組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 創建的鉤子中監聽事件
bus.$on('id-selected', function (id) {
  // ...
})

在複雜的情況下,我們應該考慮使用專門的狀態管理模式Vuex

來看一個完整的例子:
html代碼:

<div id="app">
     <comp-a v-on:id-selected="getdate"></comp-a>
     <comp-b></comp-b>
</div>

JS代碼:

var bus = new Vue();

Vue.component('comp-a', {
  template:'<button class="compa" @click="comfuna">組件A</button>',
  data:function(){
      return {
          
      }
  },
  methods:{
      comfuna(){
          bus.$emit('id-selected', 1);
          this.$emit('id-selected', 1);
      }
  }
})
Vue.component('comp-b', {
  template:'<div class="compb">組件B</div>',
  data:function(){
      return {
          
      }
  },
  mounted(){
      // 在組件 B 創建的鉤子中監聽事件
    bus.$on('id-selected', function (id) {
         console.log('在B組件中得到的值:'+id);
    })
  }
 
})
var vm = new Vue({
  el: '#app',
  data: {},
  methods:{
      getdate(value){
          console.log('得到當前的值:'+value);
      }
  }
  
})

六.使用插槽slot分發內容

在使用組件時,我們常常要像這樣組合它們:

<app>
  <app-header></app-header>
  <app-footer></app-footer>
</app>

註意兩點:

  • <app> 組件不知道它會收到什麼內容。這是由使用 <app> 的父組件決定的。
  • <app> 組件很可能有它自己的模板。

為了讓組件可以組合,我們需要一種方式來混合父組件的內容與子組件自己的模板。使用特殊的 <slot> 元素作為原始內容的插槽。

一個常見錯誤是試圖在父組件模板內將一個指令綁定到子組件的屬性/方法:

<!-- 無效 -->
<child-component v-show="someChildProperty"></child-component>

正確做法:

Vue.component('child-component', {
  // 有效,因為是在正確的作用域內
  template: '<div v-show="someChildProperty">Child</div>',
  data: function () {
    return {
      someChildProperty: true
    }
  }
})

單個插槽

假定 my-component 組件有如下模板:

<div>
  <h2>我是子組件的標題</h2>
  <slot>
    只有在沒有要分發的內容時才會顯示。
  </slot>
</div>

父組件模板:

<div>
  <h1>我是父組件的標題</h1>
  <my-component>
    <p>這是一些初始內容</p>
    <p>這是更多的初始內容</p>
  </my-component>
</div>

渲染結果:

<div>
  <h1>我是父組件的標題</h1>
  <div>
    <h2>我是子組件的標題</h2>
    <p>這是一些初始內容</p>
    <p>這是更多的初始內容</p>
  </div>
</div>

具名插槽

<slot> 元素可以用一個特殊的特性 name 來進一步配置如何分發內容。多個插槽可以有不同的名字。具名插槽將匹配內容片段中有對應 slot 特性的元素。

仍然可以有一個匿名插槽,它是預設插槽,作為找不到匹配的內容片段的備用插槽。如果沒有預設插槽,這些找不到匹配的內容片段將被拋棄。

例如,假定我們有一個 app-layout 組件,它的模板為:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

父組件模板:

<app-layout>
  <h1 slot="header">這裡可能是一個頁面標題</h1>

  <p>主要內容的一個段落。</p>
  <p>另一個主要段落。</p>

  <p slot="footer">這裡有一些聯繫信息</p>
</app-layout>

渲染結果為:

<div class="container">
  <header>
    <h1>這裡可能是一個頁面標題</h1>
  </header>
  <main>
    <

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫在前面 在我們操作頁面跳轉時,如果當前的類不是UIViewcontroller(下麵用VC表示),你會不會寫一個代理,或者block給VC傳遞信息,然後在VC裡面進行 拿tableViewCell做例子,如果每個頁面展示的tableViewCell中,如果存在不少的這樣操作,就會寫很多代理或者bl ...
  • 事務是一些列的資料庫操作,是資料庫應用程式的基本邏輯單位。事務處理技術主要包括併發控制技術和資料庫恢復技術。併發控制和資料庫恢復機制是資料庫管理系統的重要組成部分,併發控制機制用來控制多個事務的並行運行,避免它們之間的互相干擾,保證每個事務都產生正確的結果。資料庫恢復機制用來進行系統失敗後的恢復處理 ...
  • HTML5 source標簽是一種媒介元素(比如 <video> 和 <audio>)來定義媒介資源。<source> 標簽允許您規定可替換的視頻/音頻文件供瀏覽器根據它對媒體類型或者編解碼器的支持進行選擇。 這裡主機吧給大家講一下source標簽的應用屬性和實例。 <source>標簽屬性: <s ...
  • 去年年底發佈的parcel.js在年底可謂是火了一把,短短一個多月的時間在GitHub熱門排行榜上名列前茅。因其幾乎零配置的易用性,相比Webpack的複雜配置收穫了大量關註及好評,甚至有人預言未來大有超過Webpack之趨。我也趕緊嘗試一下,發現確實非常簡單易用,但是一開始,插件還是比較少,相信未 ...
  • 創建新 HTML 元素 管理 jQuery 集合 ...
  • 基本選擇器 html 代碼如下,後面的 js 使用的 html 基本大同小異。 js 代碼如下: 根據層級查找元素 js 代碼如下: 通過屬性來選擇元素 過濾器 表單過濾器及自定義過濾器 ...
  • CSS3時鐘 css 始終效果演示 ... ...
  • 安靜的敲著鍵盤,已勢不可擋的姿勢逼近php,我想我是一個幸福的人,未來不可期,做好現在,偶爾寫著自己能看懂的API,慢慢悠悠的回味一下前端基礎知識。 本文盒模型理解。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...